Greenness Exposure Assessment in Environmental Health Research
Amman, July 5th 2025
Leire Luque García
University of California San Diego
EXERCISE
1: Mitigation pathway
In this exercise, we explore how different greenness metrics
influence health through the mitigation pathway. As has already been
noted, the mitigation pathway influences human health by reducing
environmental stressors, including air pollution, heat, and noise,
through the presence of surrounding vegetation.
DESCRIPTION
We conducted a prospective study involving 6,243 adult participants
monitored during the warm season (May to September), to investigate the
potential influence of mean daytime temperature on heart rate, and
whether this association is modified by surrounding vegetation. Each
participant was equipped with a validated wearable device capable of
continuously recording daytime heart rates. NDVI and tree cover (%) were
estimated at the residential level using remote sensing data aggregated
within a 500-meter buffer surrounding each participant’s home address.
In this analysis, NDVI and tree cover are treated as potential effect
modifiers of the association between ambient daytime temperature and
physiological stress, as reflected by heart rate.
install.packages("readr")
install.packages("dplyr")
install.packages("data.table")
install.packages("ggplot2")
install.packages("skimr")
install.packages("patchwork")
install.packages("broom")
install.packages("ggeffects")
We will start installing the required packages.
library(readr)
Mitigation <- read_csv("Mitigation.csv")
Next, load the synthetic dataset titled “Mitigation.csv”.
str(Mitigation)
Examine the structure of the dataset. The “Mitigation” dataset
simulates data for 6,243 adult participants with the following
variables:
- id: Indentification number
- mean_temp: Average daytime temperature (°C)
- ndvi: Normalized Difference Vegetation Index (NDVI)
within a 500-m buffer of the residence
- tree_cover: Percentage of tree cover within a 500-m
buffer of the residence
- mean_hr: Average daytime heart rate (beats per
minute)
- sex: Sex (Female or Male)
- age: Age (years)
- ses: Socioeconomic status (I (highest) to V
(lowest))
Mitigation$sex <- factor(Mitigation$sex, labels = c("Female", "Male"))
Mitigation$ses <- factor(Mitigation$ses, labels = c("I", "II", "III", "IV", "V"))
Recode categorical variables in the “Mitigation” dataset as
factor.
library(skimr)
Obtain descriptive statistics for the exposure and outcome variables
in the “Mitigation” dataset using “skimr”.
skim(Mitigation[, c("mean_temp", "ndvi", "tree_cover", "mean_hr")])
Check the distribution of the exposure and outcome variables.
Mitigation$ndvi_tertile <- cut(Mitigation$ndvi,
breaks = quantile(Mitigation$ndvi, probs = c(0, 1/3, 2/3, 1), na.rm = TRUE),
include.lowest = TRUE,
labels = c("Low", "Medium", "High"))
Mitigation$tc_tertile <- cut(Mitigation$tree_cover,
breaks = quantile(Mitigation$tree_cover, probs = c(0, 1/3, 2/3, 1), na.rm = TRUE),
include.lowest = TRUE,
labels = c("Low", "Medium", "High"))
Create tertiles for NDVI and tree cover.
Mitigation$ndvi_tertile <- factor(Mitigation$ndvi_tertile, levels = c("Low", "Medium", "High"))
Mitigation$tc_tertile <- factor(Mitigation$tc_tertile, levels = c("Low", "Medium", "High"))
Recode as factors.
model_mitigation <- lm(mean_hr ~ mean_temp + sex + age + ses, data = Mitigation)
This linear regression model assesses the association between mean
daytime temperture (ºC) and mean heart rate (bpm), adjusting for sex,
age, and socioeconomic status (SES).
summary(model_mitigation)
Interpretation
A 1°C increase in mean daytime
temperature is associated with a 0.96 bpm increase in mean heart rate,
adjusting for sex, age, and socioeconomic status (SES). For example, a
5°C increase would correspond to an approximate 4.8 bpm increase in
heart rate. The model explains approximately 6.8% of the variance in
heart rate. The residual standard error is 11.56, suggesting that
predicted heart rate values deviate on average by around ±12 bpm from
observed values. Overall, the model is statistically significant (p <
0.001).
Now we will assess effect modification across tertiles.
library(ggeffects)
Load the “ggeffects” package to extract predicted (marginal) effects
from regression models, including models with interaction terms. These
predictions are adjusted for any confounders included in the model.
model_ndvi_interaction <- lm(mean_hr ~ mean_temp * ndvi_tertile + sex + age + ses, data = Mitigation)
model_tc_interaction <- lm(mean_hr ~ mean_temp * tc_tertile + sex + age + ses, data = Mitigation)
Fit linear regression models with an interaction term.
pred_ndvi <- ggpredict(model_ndvi_interaction, terms = c("mean_temp", "ndvi_tertile"))
pred_tc <- ggpredict(model_tc_interaction, terms = c("mean_temp", "tc_tertile"))
This function calculates model-predicted heart rates across a range
of temperature values, separately for each tertile.
library(patchwork)
plot_ndvi <- plot(pred_ndvi) +
labs(
title = "Effect Modification by NDVI",
x = "Mean Daytime Temperature (°C)",
y = "Predicted Mean Heart Rate (bpm)",
color = "NDVI"
) +
theme_minimal()
plot_tc <- plot(pred_tc) +
labs(
title = "Effect Modification by Tree Cover",
x = "Mean Daytime Temperature (°C)",
y = "Predicted Mean Heart Rate (bpm)",
color = "Tree Cover"
) +
theme_minimal()
plot_ndvi + plot_tc
Interpretation
The plots illustrate that the
association between mean daytime temperature and heart rate is modified
by surrounding vegetation. In both the NDVI and tree cover models,
higher vegetation levels are associated with a progressively weaker
temperature–heart rate relationship across tertiles. This pattern
suggests that increased vegetation may attenuate the physiological
response to heat exposure.
However, such attenuation is more pronounced in the case of tree
cover. In areas with high tree cover, the slope is almost flat,
indicating substantial mitigation of heat effects. In contrast, the
mitigation observed for high NDVI is more modest. These results suggest
that, although both metrics provide some protection, tree cover is more
effective in mitigating the physiological impacts of heat.
EXERCISE
2: Restoration pathway
This exercise examines how different greenness metrics influence
health through the restoration pathway. The restoration pathway
describes how exposure to greenness improves health through two major
theories: the Attention Restoration Theory (ART) and
the Stress Reduction Theory (SRT). The SRT and ART are
interconnected, grounded in biophilic principles, emphasizing the innate
human connection to nature. According to the biophilia hypothesis,
humans have an evolutionary tendency to seek connections with other
forms of life (Wilson, 1986).
DESCRIPTION
In this exercise, you will analyze generated data from 5,000
participants to examine how greenness exposure relates to physiological
stress, measured through cortisol levels. Greenness is assessed using
NDVI within a 500-meter buffer around the home, while weekly time spent
in green spaces (minutes) is objectively measured using individual
tracking devices.
Restoration <- read_csv("Restoration.csv")
Rows: 5000 Columns: 7── Column specification ──────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr (2): sex, ses
dbl (5): id, ndvi, green_minutes, cortisol, age
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
Load the synthetic dataset titled “Restoration.csv”.
str(Restoration)
spc_tbl_ [5,000 × 7] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
$ id : num [1:5000] 1 2 3 4 5 6 7 8 9 10 ...
$ ndvi : num [1:5000] 0.3981 0.1379 0.1031 0.0156 0.1645 ...
$ green_minutes: num [1:5000] 42 65 69 0 46 82 46 63 64 57 ...
$ cortisol : num [1:5000] 93.7 70.6 85.8 109 118.8 ...
$ sex : chr [1:5000] "Female" "Female" "Male" "Male" ...
$ age : num [1:5000] 51 48 63 42 30 47 34 36 58 43 ...
$ ses : chr [1:5000] "II" "III" "V" "V" ...
- attr(*, "spec")=
.. cols(
.. id = col_double(),
.. ndvi = col_double(),
.. green_minutes = col_double(),
.. cortisol = col_double(),
.. sex = col_character(),
.. age = col_double(),
.. ses = col_character()
.. )
- attr(*, "problems")=<externalptr>
Examine the structure of the dataset. The “Restoration” dataset
simulates data for 5,000 adult participants with the following
variables:
- id: Indentification number
- ndvi: Normalized Difference Vegetation Index (NDVI)
within a 500-m buffer of the residence
- green_minutes: Mean weekly time spent in green
spaces (minutes)
- cortisol: Hair cortisol measures (pg/mg)
- sex: Sex (Female or Male)
- age: Age (years)
- ses: Socioeconomic status, (I (highest) to V
(lowest))
Restoration$sex <- factor(Restoration$sex, labels = c("Female", "Male"))
Restoration$ses <- factor(Restoration$ses, labels = c("I", "II", "III", "IV", "V"))
Recode categorical variables in the “Restoration” dataset as
factor.
skim(Restoration[, c("ndvi", "green_minutes", "cortisol")])
── Data Summary ────────────────────────
Values
Name Restoration[, c("ndvi", "...
Number of rows 5000
Number of columns 3
_______________________
Column type frequency:
numeric 3
________________________
Group variables None
Check the distribution of the exposure and outcome variables.
model_ndvi <- lm(cortisol ~ ndvi + sex + age + ses, data = Restoration)
Fit a linear regression model to examine the relationship between
NDVI (exposure) and hair cortisol levels (outcome), adjusting for
potential confounders (sex, age, ses).
summary(model_ndvi)
Call:
lm(formula = cortisol ~ ndvi + sex + age + ses, data = Restoration)
Residuals:
Min 1Q Median 3Q Max
-91.414 -17.447 -0.172 17.602 75.980
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 81.53281 1.97741 41.232 < 2e-16 ***
ndvi -23.48901 2.74435 -8.559 < 2e-16 ***
sexMale -4.04010 0.71633 -5.640 1.79e-08 ***
age 0.29469 0.03568 8.260 < 2e-16 ***
sesII 2.73761 1.11360 2.458 0.014 *
sesIII 5.63268 1.12996 4.985 6.41e-07 ***
sesIV 8.92504 1.12910 7.905 3.28e-15 ***
sesV 12.86420 1.12337 11.451 < 2e-16 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 25.29 on 4992 degrees of freedom
Multiple R-squared: 0.06367, Adjusted R-squared: 0.06235
F-statistic: 48.49 on 7 and 4992 DF, p-value: < 2.2e-16
Interpretation
A 1-unit increase in NDVI (from 0
to 1) is associated with a 23.5-unit decrease in hair cortisol,
adjusting for other variables. This is difficult to interpret. Using the
IQR instead, allows to interpret the effect of NDVI in terms of a
typical, realistic change in exposure, making the results clearer.
iqr_ndvi <- IQR(Restoration$ndvi)
Restoration$ndvi_iqr <- Restoration$ndvi/iqr_ndvi
model_ndvi_iqr <- lm(cortisol ~ ndvi_iqr + sex + age + ses, data = Restoration)
Standarize NDVI dividing it by its IQR to make the effect size more
interpretable, then model its association with hair cortisol, adjusting
for key covariates.
summary(model_ndvi_iqr)
Call:
lm(formula = cortisol ~ ndvi_iqr + sex + age + ses, data = Restoration)
Residuals:
Min 1Q Median 3Q Max
-91.414 -17.447 -0.172 17.602 75.980
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 81.53281 1.97741 41.232 < 2e-16 ***
ndvi_iqr -4.30723 0.50324 -8.559 < 2e-16 ***
sexMale -4.04010 0.71633 -5.640 1.79e-08 ***
age 0.29469 0.03568 8.260 < 2e-16 ***
sesII 2.73761 1.11360 2.458 0.014 *
sesIII 5.63268 1.12996 4.985 6.41e-07 ***
sesIV 8.92504 1.12910 7.905 3.28e-15 ***
sesV 12.86420 1.12337 11.451 < 2e-16 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 25.29 on 4992 degrees of freedom
Multiple R-squared: 0.06367, Adjusted R-squared: 0.06235
F-statistic: 48.49 on 7 and 4992 DF, p-value: < 2.2e-16
Interpretation
A 1 IQR increase in NDVI is
associated with a 4.31 pg/mg decrease in cortisol, adjusting for sex,
age, and SES. The model explains 6.4% of the variance in hair cortisol
levels. The residual standard error of 25.29 is relatively high, meaning
that predictions from the model often deviate substantially from actual
hair cortisol values. Overall, the model is statistically significant (p
< 0.001).
model_time <- lm(cortisol ~ green_minutes + ses + age + sex, data = Restoration)
Fit a linear regression model to examine the relationship between
hair cortisol levels (outcome) and mean weekly time spent in green
spaces (exposure), adjusting for potential confounders.
summary(model_time)
Call:
lm(formula = cortisol ~ green_minutes + ses + age + sex, data = Restoration)
Residuals:
Min 1Q Median 3Q Max
-93.191 -17.135 -0.321 17.252 81.090
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 86.31237 2.07579 41.580 < 2e-16 ***
green_minutes -0.14979 0.01335 -11.223 < 2e-16 ***
sesII 1.91357 1.10992 1.724 0.084758 .
sesIII 4.19615 1.13207 3.707 0.000212 ***
sesIV 6.88432 1.13954 6.041 1.64e-09 ***
sesV 10.05635 1.14318 8.797 < 2e-16 ***
age 0.27694 0.03556 7.787 8.26e-15 ***
sexMale -3.93888 0.71249 -5.528 3.40e-08 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 25.16 on 4992 degrees of freedom
Multiple R-squared: 0.07331, Adjusted R-squared: 0.07201
F-statistic: 56.41 on 7 and 4992 DF, p-value: < 2.2e-16
Interpretation
A 1-minute increase in the mean
weekly time spent in green spaces is associated with a 0.15 pg/mg
decrease in hair cortisol, adjusting for SES, age, and sex. For example,
an increase of 30 minutes per week would correspond to a 4.5 pg/mg
reduction in cortisol levels. The model explains 7.3% of the variance in
hair cortisol levels. The residual standard error is 25.16, indicating
that predicted cortisol values often deviate notably from observed
values. Overall, the model is statistically significant (p <
0.001).
library(patchwork)
Load the required package to combine ggplot objects.
p1 <- ggplot(Restoration, aes(x = ndvi, y = cortisol)) +
geom_point(alpha = 0.3, color = "#145A32") +
geom_smooth(method = "lm", color = "#27AE60", fill = "#ABEBC6") +
labs(
title = "NDVI vs. Hair Cortisol",
x = "NDVI (Residential Greenness)",
y = "Hair Cortisol (pg/mg)"
) +
theme_minimal(base_size = 10)
Create a scatterplot showing the association between NDVI and hair
cortisol levels.
p2 <- ggplot(Restoration, aes(x = green_minutes, y = cortisol)) +
geom_point(alpha = 0.3, color = "#2C3E50") +
geom_smooth(method = "lm", color = "#2980B9", fill = "#85C1E9") +
labs(
title = "Green Space Time vs. Hair Cortisol",
x = "Green Space Time (minutes/week)",
y = "Hair Cortisol (pg/mg)"
) +
theme_minimal(base_size = 10)
Create a second scatterplot on the association between mean weekly
time spent in green spaces and hair cortisol levels.
combined_plot <- p1 + p2
combined_plot

Combine plots for comparison using patchwork.
Interpretation
While both “NDVI” and “Green
Space Time” are significantly associated with lower hair cortisol,
“Green Space Time” shows a stronger statistical association and slightly
better model fit. This suggests that while NDVI is a widely available
and straightforward greenness metric, the restoration pathway likely
involves direct interaction with nature. Therefore, studies should
consider not only spatial availability of greenness but also the
frequency and duration of individual exposure.
EXERCISE
3: Instoration pathway
This exercise examines how different greenness metrics influence
health through the instoration pathway. The instoration or capacity
building pathway, highlights how natural environments promote
health-related behaviors by encouraging physical activity and social
cohesion.
Green spaces often provide a secure, accessible, and attractive
setting in which to be physically active. In this regard, numerous
studies have found positive associations between increased exposure to
green environments and higher levels of physical activity (Gianfredi et
al., 2021), which, in turn, is linked to improved physical (Bull et al.,
2020) and mental health (Rodriguez-Ayllon et al., 2019).
DESCRIPTION
In this exercise, you will analyze generated data from 5,000
participants to examine how proximity to green spaces relates to
physical activity, measured as weekly minutes using individual tracking
devices. Greenness exposure is assessed using two different distance
measures based on the residential address:
- Straight-line distance to the closest green space (in meters)
- Network distance to the closest green space (in meters)
Instoration <- read_csv("Instoration.csv")
Rows: 5000 Columns: 7── Column specification ──────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr (2): sex, ses
dbl (5): id, straight_distance, network_distance, weekly_pa, age
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
Load the synthetic dataset titled “Instoration.csv”.
str(Instoration)
spc_tbl_ [5,000 × 7] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
$ id : num [1:5000] 1 2 3 4 5 6 7 8 9 10 ...
$ straight_distance: num [1:5000] 433 62 296 341 233 214 188 266 148 503 ...
$ network_distance : num [1:5000] 904 257 341 682 257 279 377 755 599 791 ...
$ weekly_pa : num [1:5000] 292 295 303 305 271 296 315 262 278 280 ...
$ sex : chr [1:5000] "Male" "Male" "Male" "Male" ...
$ age : num [1:5000] 36 50 43 58 60 38 52 68 54 51 ...
$ ses : chr [1:5000] "V" "I" "III" "V" ...
- attr(*, "spec")=
.. cols(
.. id = col_double(),
.. straight_distance = col_double(),
.. network_distance = col_double(),
.. weekly_pa = col_double(),
.. sex = col_character(),
.. age = col_double(),
.. ses = col_character()
.. )
- attr(*, "problems")=<externalptr>
Examine the structure of the dataset. The “Instoration” dataset
simulates data for 5,000 adult participants with the following
variables:
- id: Indentification number
- straight_distance: Straight-line distance to the
nearest green space (meters) based on the residence
- network_distance: Network distance to the nearest
green space (meters) based on the residence
- weekly_pa: Weekly physical activity (minutes)
- sex: Sex (Female or Male)
- age: Age (years)
- ses: Socioeconomic status, (I (highest) to V
(lowest))
Instoration$sex <- factor(Instoration$sex, labels = c("Female", "Male"))
Instoration$ses <- factor(Instoration$ses, labels = c("I", "II", "III", "IV", "V"))
Recode categorical variables in the “Instoration” dataset as
factor.
skim(Instoration[, c("straight_distance", "network_distance", "weekly_pa")])
── Data Summary ────────────────────────
Values
Name Instoration[, c("straight...
Number of rows 5000
Number of columns 3
_______________________
Column type frequency:
numeric 3
________________________
Group variables None
Check the distribution of the exposure and outcome variables.
model_straight <- lm(weekly_pa ~ straight_distance + sex + age + ses, data = Instoration)
Fit a linear regression model to examine the relationship between
straight-line distance to the nearest green space
(exposure) and weekly physical activity time (outcome),
adjusting for potential confounders (sex, age, ses).
summary(model_straight)
Call:
lm(formula = weekly_pa ~ straight_distance + sex + age + ses,
data = Instoration)
Residuals:
Min 1Q Median 3Q Max
-97.075 -20.316 -0.386 19.883 119.331
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 300.585497 2.248761 133.667 <2e-16 ***
straight_distance -0.023692 0.001754 -13.506 <2e-16 ***
sexMale -1.581549 0.841731 -1.879 0.0603 .
age -0.062596 0.037653 -1.662 0.0965 .
sesII 0.334750 1.311055 0.255 0.7985
sesIII -0.119385 1.312486 -0.091 0.9275
sesIV 1.203676 1.320661 0.911 0.3621
sesV 0.424646 1.324429 0.321 0.7485
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 29.72 on 4992 degrees of freedom
Multiple R-squared: 0.03637, Adjusted R-squared: 0.03502
F-statistic: 26.91 on 7 and 4992 DF, p-value: < 2.2e-16
Interpretation
A 100-meter increase in
straight-line distance to the nearest green space is associated with a
2.37-minute decrease in weekly physical activity, adjusting for sex,
age, and socioeconomic status. The model explains 3.6% of the variance
in weekly physical activity. The residual standard error indicates a
substantial unexplained variability of around 30 minutes. Although the
association is statistically significant (p < 0.001), the overall
effect size is small, and the explanatory power is limited.
model_network <- lm(weekly_pa ~ network_distance + sex + age + ses, data = Instoration)
Fit a linear regression model to examine the relationship between
network distance to the nearest green space (exposure)
and weekly physical activity time (outcome), adjusting
for potential confounders (sex, age, ses).
summary(model_network)
Call:
lm(formula = weekly_pa ~ network_distance + sex + age + ses,
data = Instoration)
Residuals:
Min 1Q Median 3Q Max
-97.596 -20.786 -0.414 20.064 122.487
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 306.284376 2.384980 128.422 <2e-16 ***
network_distance -0.021386 0.001513 -14.132 <2e-16 ***
sexMale -1.668671 0.840360 -1.986 0.0471 *
age -0.063695 0.037591 -1.694 0.0903 .
sesII 0.347520 1.308872 0.266 0.7906
sesIII -0.161458 1.310314 -0.123 0.9019
sesIV 1.167341 1.318413 0.885 0.3760
sesV 0.205750 1.322074 0.156 0.8763
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 29.67 on 4992 degrees of freedom
Multiple R-squared: 0.03958, Adjusted R-squared: 0.03823
F-statistic: 29.39 on 7 and 4992 DF, p-value: < 2.2e-16
Interpretation
A 100-meter increase in network
distance to the nearest green space is associated with a 2.14-minute
decrease in weekly physical activity, adjusting for sex, age, and
socioeconomic status. The model explains 4.0% of the variance in weekly
physical activity. The residual standard error indicates a substantial
unexplained variability of around 30 minutes. Although the association
is statistically significant (p < 0.001), the overall effect size is
small, and the explanatory power is limited.
p1 <- ggplot(Instoration, aes(x = straight_distance, y = weekly_pa)) +
geom_point(alpha = 0.3, color = "#ff70a6") +
geom_smooth(method = "lm", color = "#ff0054", fill = "#F796BB") +
labs(
title = "Straight-line vs. Physical Activity",
x = "Straight-line Green Space (meters)",
y = "Physical Activity (minutes/week)"
) +
theme_minimal(base_size = 10)
Create a scatterplot showing the association between straight-line
distance to the closest green space and weekly physical activity.
p2 <- ggplot(Instoration, aes(x = network_distance, y = weekly_pa)) +
geom_point(alpha = 0.3, color = "#E4B0EE") +
geom_smooth(method = "lm", color = "#BE39D8", fill = "#D398DF") +
labs(
title = "Network vs. Physical Activity",
x = "Network Green Space (meters)",
y = "Physical Activity (minutes/week)"
) +
theme_minimal(base_size = 10)
Create a scatterplot showing the association between network distance
to the closest green space and weekly physical activity.
combined_plot <- p1 + p2
combined_plot

Combine plots for comparison using patchwork.
Interpretation
While both “straight-line
distance” and “network distance” to the nearest green space are
significantly associated with lower weekly physical activity, “network
distance” shows a slightly stronger statistical association (t = –14.13
vs. –13.51) and better model fit (R² = 4.0% vs. 3.6%). These results
suggest that network distance offers a more realistic estimation of
green space accessibility, as it is constructed based on actual
routes.
EXERCISE
4: Biodiversity pathway
This exercise focuses on the biodiversity pathway. Biodiversity is a
fundamental determinant of health, influencing both physical and
psychological well-being. While biodiversity generally benefits human
health, it also presents associated risks, including exposure to
airborne allergens and volatile organic compounds that may trigger
allergic reactions (Marselle et al., 2021).
DESCRIPTION
You will analyze generated data from 4,730 participants to examine
how vegetation diversity is associated with allergic rhinitis symptoms
(e.g., sneezing, nasal congestion, itchy eyes), measured as the total
number of antihistamine pills taken per year.
Vegetation diversity is modeled as a continuous index based on the
Shannon diversity index, which accounts for both abundance and evenness
of the species present. The index ranges from 0 (no diversity) to
approximately 2.5 (high diversity), with higher values indicating
greater ecological diversity in the surrounding plant environment.
library(readr)
Biodiversity <- read_csv("Biodiversity.csv")
Rows: 4730 Columns: 7── Column specification ──────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr (3): urbanicity, sex, ses
dbl (4): id, veg_diversity, allergy_med, age
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
Load the synthetic dataset titled “Biodiversity.csv”.
str(Biodiversity)
spc_tbl_ [4,730 × 7] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
$ id : num [1:4730] 1 2 3 4 5 6 7 8 9 10 ...
$ veg_diversity: num [1:4730] 1.91 1.37 1.9 2.07 1.56 2.23 1.33 1.46 1.95 1.92 ...
$ urbanicity : chr [1:4730] "Suburban" "Urban" "Urban" "Suburban" ...
$ allergy_med : num [1:4730] 4 7 7 8 5 12 6 5 11 7 ...
$ sex : chr [1:4730] "Male" "Female" "Male" "Male" ...
$ age : num [1:4730] 53 40 51 52 39 70 59 44 49 30 ...
$ ses : chr [1:4730] "I" "V" "III" "III" ...
- attr(*, "spec")=
.. cols(
.. id = col_double(),
.. veg_diversity = col_double(),
.. urbanicity = col_character(),
.. allergy_med = col_double(),
.. sex = col_character(),
.. age = col_double(),
.. ses = col_character()
.. )
- attr(*, "problems")=<externalptr>
Examine the structure of the dataset. The “Biodiversity” dataset
simulates data for 4,730 adult participants with the following
variables:
- id: Indentification number
- veg_diversity: Vegetation diversity based on the
Shannon diversity index, estimated within a 300-meter buffer around each
participant’s residence.
- urbanicity: Urbanization level (Rural, Suburban or
Urban) of the neighborhood area.
- allergy_med: The total number of antihistamine
pills consumed over the the past year, as a proxy of allergic rhinitis
symptom burden.
- sex: Sex (Female or Male)
- age: Age (years)
- ses: Socioeconomic status (I (highest) to V
(lowest))
Biodiversity$urbanicity <- factor(Biodiversity$urbanicity, labels = c("Rural", "Suburban", "Urban"))
Biodiversity$sex <- factor(Biodiversity$sex, labels = c("Female", "Male"))
Biodiversity$ses <- factor(Biodiversity$ses, labels = c("I", "II", "III", "IV", "V"))
Recode categorical variables in the “Biodiversity” dataset as
factor.
library(skimr)
skim(Biodiversity[, c("veg_diversity", "allergy_med")])
── Data Summary ────────────────────────
Values
Name Biodiversity[, c("veg_div...
Number of rows 4730
Number of columns 2
_______________________
Column type frequency:
numeric 2
________________________
Group variables None
Check the distribution of the exposure and outcome variables.
model_biodiversity <- lm(allergy_med ~ veg_diversity + sex + age + ses, data = Biodiversity)
Fit a linear regression model to examine the relationship between
vegetation diversity (exposure) and
antihistamine pills per year (outcome), adjusting for
potential confounders (sex, age, ses).
summary(model_biodiversity)
Call:
lm(formula = allergy_med ~ veg_diversity + sex + age + ses, data = Biodiversity)
Residuals:
Min 1Q Median 3Q Max
-9.1043 -2.5355 -0.3814 2.2014 15.2418
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) -1.8879709 0.3396285 -5.559 2.86e-08 ***
veg_diversity 4.5195009 0.1353776 33.384 < 2e-16 ***
sexMale 0.1948230 0.0994269 1.959 0.0501 .
age 0.0072995 0.0043829 1.665 0.0959 .
sesII -0.0001596 0.1551195 -0.001 0.9992
sesIII -0.2834895 0.1545145 -1.835 0.0666 .
sesIV -0.1052469 0.1560432 -0.674 0.5000
sesV -0.2214779 0.1584723 -1.398 0.1623
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 3.418 on 4722 degrees of freedom
Multiple R-squared: 0.193, Adjusted R-squared: 0.1918
F-statistic: 161.3 on 7 and 4722 DF, p-value: < 2.2e-16
Interpretation
A unit increase in vegetation
diversity is associated with an estimated increase of 4.52 antihistamine
pills per year, adjusting for sex, age, and socioeconomic status (p <
0.001). The model explains 19.3% of the variance in antihistamine use,
with a residual standard error of 3.42 pills, which indicates a moderate
unexplained variability.
library(dplyr)
Attaching package: ‘dplyr’
The following objects are masked from ‘package:data.table’:
between, first, last
The following objects are masked from ‘package:stats’:
filter, lag
The following objects are masked from ‘package:base’:
intersect, setdiff, setequal, union
library(broom)
model_coefficients_urbanicity <- Biodiversity %>%
group_by(urbanicity) %>%
do(tidy(lm(allergy_med ~ veg_diversity + sex + age + ses, data = .))) %>%
filter(term == "veg_diversity")
Fit the previous linear regression model, but this time stratified by
urbanization level. This approach allows to examine
whether the strength or direction of the association between vegetation
diversity and allergic rhinitis symptoms varies across rural, suburban,
and urban residential contexts.
print(model_coefficients_urbanicity)
Interpretation
When stratified by urbanization
level, the association between vegetation diversity and antihistamine
use differs in magnitude. In urban areas, a unit increase in vegetation
diversity is associated with an estimated 4.47 pill increase per year (p
< 0.001), after adjusting for sex, age, and socioeconomic status. In
suburban areas, the increase corresponds to 1.41 pills per year (p <
0.001), while in rural areas, the association is smaller at 0.56 pills
per year (p < 0.001). These results suggest that the health impact of
vegetation diversity may be modified by urbanization level.
ggplot(Biodiversity, aes(x = veg_diversity, y = allergy_med, color = urbanicity)) +
geom_point(alpha = 0.4) +
geom_smooth(method = "lm", se = FALSE, size = 1.2) +
scale_color_manual(
values = c("Rural" = "#0BDA51", "Suburban" = "#1E90FF", "Urban" = "#FF3800") # you can change these
) +
labs(
title = "Vegetation Diversity vs. Allergy Medication",
x = "Vegetation Diversity",
y = "Allergy Medication (pills/year)",
color = "Urbanization"
) +
theme_minimal()
Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
Please use `linewidth` instead.

Interpretation
The relationship between
urbanization and allergic symptoms (e.g.,asthma, allergic rhinitis,
eczema, food allergies) has been widely studied, and epidemiological
evidence consistently shows higher prevalence and severity of allergic
diseases among individuals residing in urban areas when compared to
those that reside in rural settings.This association may be partly
attributed to reduced microbial exposure in urban environments.
Urbanization has been associated to lower microbial diversity, which is
considered an important factor in the development of allergic
sensitization. According to the hygiene hypothesis, reduced exposure to
microbes in early life limits immune system stimulation, potentially
increasing the risk of allergic diseases.
End of the analysis — Thank you for joining the workshop!
LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKPGRpdiBzdHlsZT0idGV4dC1hbGlnbjogY2VudGVyOyI+CiAgPGgxIHN0eWxlPSJmb250LXNpemU6IDQ0cHg7IGNvbG9yOiBncmVlbjsgZm9udC13ZWlnaHQ6IGJvbGQ7IG1hcmdpbi1ib3R0b206IDA7Ij4KICAgIEdyZWVubmVzcyBFeHBvc3VyZSBBc3Nlc3NtZW50IGluIEVudmlyb25tZW50YWwgSGVhbHRoIFJlc2VhcmNoCiAgPC9oMT4KICA8cCBzdHlsZT0iZm9udC1zaXplOiAyMHB4OyBtYXJnaW4tdG9wOiAwOyI+QW1tYW4sIEp1bHkgNXRoIDIwMjU8L3A+CjwvZGl2PgoKPGRpdiBzdHlsZT0idGV4dC1hbGlnbjogY2VudGVyOyI+CiAgPGgxIHN0eWxlPSJmb250LXNpemU6IDIwcHg7IG1hcmdpbi1ib3R0b206IDA7Ij4KICAgIExlaXJlIEx1cXVlIEdhcmPDrWEKICA8L2gxPgogIDxwIHN0eWxlPSJmb250LXNpemU6IDIwcHg7IG1hcmdpbi10b3A6IDA7Ij4KICAgIFVuaXZlcnNpdHkgb2YgQ2FsaWZvcm5pYSBTYW4gRGllZ28KICA8L3A+CjwvZGl2PgoKClsqKkVYRVJDSVNFIDE6KiogTWl0aWdhdGlvbiBwYXRod2F5XXtzdHlsZT0iZm9udC1zaXplOjI0cHg7IHRleHQtZGVjb3JhdGlvbjp1bmRlcmxpbmU7Y29sb3I6Z3JlZW47In0KCkluIHRoaXMgZXhlcmNpc2UsIHdlIGV4cGxvcmUgaG93IGRpZmZlcmVudCBncmVlbm5lc3MgbWV0cmljcyBpbmZsdWVuY2UgaGVhbHRoIHRocm91Z2ggdGhlIG1pdGlnYXRpb24gcGF0aHdheS4gQXMgaGFzIGFscmVhZHkgYmVlbiBub3RlZCwgdGhlIG1pdGlnYXRpb24gcGF0aHdheSBpbmZsdWVuY2VzIGh1bWFuIGhlYWx0aCBieSByZWR1Y2luZyBlbnZpcm9ubWVudGFsIHN0cmVzc29ycywgaW5jbHVkaW5nIGFpciBwb2xsdXRpb24sIGhlYXQsIGFuZCBub2lzZSwgdGhyb3VnaCB0aGUgcHJlc2VuY2Ugb2Ygc3Vycm91bmRpbmcgdmVnZXRhdGlvbi4KCioqREVTQ1JJUFRJT04qKgoKV2UgY29uZHVjdGVkIGEgcHJvc3BlY3RpdmUgc3R1ZHkgaW52b2x2aW5nIDYsMjQzIGFkdWx0IHBhcnRpY2lwYW50cyBtb25pdG9yZWQgZHVyaW5nIHRoZSB3YXJtIHNlYXNvbiAoTWF5IHRvIFNlcHRlbWJlciksIHRvIGludmVzdGlnYXRlIHRoZSBwb3RlbnRpYWwgaW5mbHVlbmNlIG9mIG1lYW4gZGF5dGltZSB0ZW1wZXJhdHVyZSBvbiBoZWFydCByYXRlLCBhbmQgd2hldGhlciB0aGlzIGFzc29jaWF0aW9uIGlzIG1vZGlmaWVkIGJ5IHN1cnJvdW5kaW5nIHZlZ2V0YXRpb24uIEVhY2ggcGFydGljaXBhbnQgd2FzIGVxdWlwcGVkIHdpdGggYSB2YWxpZGF0ZWQgd2VhcmFibGUgZGV2aWNlIGNhcGFibGUgb2YgY29udGludW91c2x5IHJlY29yZGluZyBkYXl0aW1lIGhlYXJ0IHJhdGVzLiBORFZJIGFuZCB0cmVlIGNvdmVyICglKSB3ZXJlIGVzdGltYXRlZCBhdCB0aGUgcmVzaWRlbnRpYWwgbGV2ZWwgdXNpbmcgcmVtb3RlIHNlbnNpbmcgZGF0YSBhZ2dyZWdhdGVkIHdpdGhpbiBhIDUwMC1tZXRlciBidWZmZXIgc3Vycm91bmRpbmcgZWFjaCBwYXJ0aWNpcGFudOKAmXMgaG9tZSBhZGRyZXNzLiBJbiB0aGlzIGFuYWx5c2lzLCBORFZJIGFuZCB0cmVlIGNvdmVyIGFyZSB0cmVhdGVkIGFzIHBvdGVudGlhbCBlZmZlY3QgbW9kaWZpZXJzIG9mIHRoZSBhc3NvY2lhdGlvbiBiZXR3ZWVuIGFtYmllbnQgZGF5dGltZSB0ZW1wZXJhdHVyZSBhbmQgcGh5c2lvbG9naWNhbCBzdHJlc3MsIGFzIHJlZmxlY3RlZCBieSBoZWFydCByYXRlLgoKYGBge3J9Cmluc3RhbGwucGFja2FnZXMoInJlYWRyIikKaW5zdGFsbC5wYWNrYWdlcygiZHBseXIiKQppbnN0YWxsLnBhY2thZ2VzKCJkYXRhLnRhYmxlIikKaW5zdGFsbC5wYWNrYWdlcygiZ2dwbG90MiIpCmluc3RhbGwucGFja2FnZXMoInNraW1yIikKaW5zdGFsbC5wYWNrYWdlcygicGF0Y2h3b3JrIikKaW5zdGFsbC5wYWNrYWdlcygiYnJvb20iKQppbnN0YWxsLnBhY2thZ2VzKCJnZ2VmZmVjdHMiKQpgYGAKV2Ugd2lsbCBzdGFydCBpbnN0YWxsaW5nIHRoZSByZXF1aXJlZCBwYWNrYWdlcy4KCmBgYHtyfQpsaWJyYXJ5KHJlYWRyKQpNaXRpZ2F0aW9uIDwtIHJlYWRfY3N2KCJNaXRpZ2F0aW9uLmNzdiIpCmBgYApOZXh0LCBsb2FkIHRoZSBzeW50aGV0aWMgZGF0YXNldCB0aXRsZWQgIk1pdGlnYXRpb24uY3N2Ii4KCmBgYHtyfQpzdHIoTWl0aWdhdGlvbikKYGBgCkV4YW1pbmUgdGhlIHN0cnVjdHVyZSBvZiB0aGUgZGF0YXNldC4gVGhlICJNaXRpZ2F0aW9uIiBkYXRhc2V0IHNpbXVsYXRlcyBkYXRhIGZvciA2LDI0MyBhZHVsdCBwYXJ0aWNpcGFudHMgd2l0aCB0aGUgZm9sbG93aW5nIHZhcmlhYmxlczoKCi0gICAqKmlkKio6IEluZGVudGlmaWNhdGlvbiBudW1iZXIKLSAgICoqbWVhbl90ZW1wKio6IEF2ZXJhZ2UgZGF5dGltZSB0ZW1wZXJhdHVyZSAowrBDKQotICAgKipuZHZpKio6IE5vcm1hbGl6ZWQgRGlmZmVyZW5jZSBWZWdldGF0aW9uIEluZGV4IChORFZJKSB3aXRoaW4gYSA1MDAtbSBidWZmZXIgb2YgdGhlIHJlc2lkZW5jZQotICAgKip0cmVlX2NvdmVyKio6IFBlcmNlbnRhZ2Ugb2YgdHJlZSBjb3ZlciB3aXRoaW4gYSA1MDAtbSBidWZmZXIgb2YgdGhlIHJlc2lkZW5jZQotICAgKiptZWFuX2hyKio6IEF2ZXJhZ2UgZGF5dGltZSBoZWFydCByYXRlIChiZWF0cyBwZXIgbWludXRlKQotICAgKipzZXgqKjogU2V4IChGZW1hbGUgb3IgTWFsZSkKLSAgICoqYWdlKio6IEFnZSAoeWVhcnMpCi0gICAqKnNlcyoqOiBTb2Npb2Vjb25vbWljIHN0YXR1cyAoSSAoaGlnaGVzdCkgdG8gViAobG93ZXN0KSkKCmBgYHtyfQpNaXRpZ2F0aW9uJHNleCA8LSBmYWN0b3IoTWl0aWdhdGlvbiRzZXgsIGxhYmVscyA9IGMoIkZlbWFsZSIsICJNYWxlIikpCk1pdGlnYXRpb24kc2VzIDwtIGZhY3RvcihNaXRpZ2F0aW9uJHNlcywgbGFiZWxzID0gYygiSSIsICJJSSIsICJJSUkiLCAiSVYiLCAiViIpKQpgYGAKUmVjb2RlIGNhdGVnb3JpY2FsIHZhcmlhYmxlcyBpbiB0aGUgIk1pdGlnYXRpb24iIGRhdGFzZXQgYXMgZmFjdG9yLgoKYGBge3J9CmxpYnJhcnkoc2tpbXIpCmBgYApPYnRhaW4gZGVzY3JpcHRpdmUgc3RhdGlzdGljcyBmb3IgdGhlIGV4cG9zdXJlIGFuZCBvdXRjb21lIHZhcmlhYmxlcyBpbiB0aGUgIk1pdGlnYXRpb24iIGRhdGFzZXQgdXNpbmcgInNraW1yIi4KCmBgYHtyfQpza2ltKE1pdGlnYXRpb25bLCBjKCJtZWFuX3RlbXAiLCAibmR2aSIsICJ0cmVlX2NvdmVyIiwgIm1lYW5faHIiKV0pCmBgYApDaGVjayB0aGUgZGlzdHJpYnV0aW9uIG9mIHRoZSBleHBvc3VyZSBhbmQgb3V0Y29tZSB2YXJpYWJsZXMuIAoKYGBge3J9IAoKTWl0aWdhdGlvbiRuZHZpX3RlcnRpbGUgPC0gY3V0KE1pdGlnYXRpb24kbmR2aSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWtzID0gcXVhbnRpbGUoTWl0aWdhdGlvbiRuZHZpLCBwcm9icyA9IGMoMCwgMS8zLCAyLzMsIDEpLCBuYS5ybSA9IFRSVUUpLAogICAgICAgICAgICAgICAgICAgICAgICAgICBpbmNsdWRlLmxvd2VzdCA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIkxvdyIsICJNZWRpdW0iLCAiSGlnaCIpKQoKTWl0aWdhdGlvbiR0Y190ZXJ0aWxlIDwtIGN1dChNaXRpZ2F0aW9uJHRyZWVfY292ZXIsCiAgICAgICAgICAgICAgICAgICAgICAgICBicmVha3MgPSBxdWFudGlsZShNaXRpZ2F0aW9uJHRyZWVfY292ZXIsIHByb2JzID0gYygwLCAxLzMsIDIvMywgMSksIG5hLnJtID0gVFJVRSksCiAgICAgICAgICAgICAgICAgICAgICAgICBpbmNsdWRlLmxvd2VzdCA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJMb3ciLCAiTWVkaXVtIiwgIkhpZ2giKSkKCmBgYApDcmVhdGUgdGVydGlsZXMgZm9yIE5EVkkgYW5kIHRyZWUgY292ZXIuCgpgYGB7cn0KTWl0aWdhdGlvbiRuZHZpX3RlcnRpbGUgPC0gZmFjdG9yKE1pdGlnYXRpb24kbmR2aV90ZXJ0aWxlLCBsZXZlbHMgPSBjKCJMb3ciLCAiTWVkaXVtIiwgIkhpZ2giKSkKTWl0aWdhdGlvbiR0Y190ZXJ0aWxlIDwtIGZhY3RvcihNaXRpZ2F0aW9uJHRjX3RlcnRpbGUsIGxldmVscyA9IGMoIkxvdyIsICJNZWRpdW0iLCAiSGlnaCIpKQpgYGAKUmVjb2RlIGFzIGZhY3RvcnMuCgpgYGB7cn0KbW9kZWxfbWl0aWdhdGlvbiA8LSBsbShtZWFuX2hyIH4gbWVhbl90ZW1wICsgc2V4ICsgYWdlICsgc2VzLCBkYXRhID0gTWl0aWdhdGlvbikKYGBgClRoaXMgbGluZWFyIHJlZ3Jlc3Npb24gbW9kZWwgYXNzZXNzZXMgdGhlIGFzc29jaWF0aW9uIGJldHdlZW4gbWVhbiBkYXl0aW1lIHRlbXBlcnR1cmUgKMK6QykgYW5kIG1lYW4gaGVhcnQgcmF0ZSAoYnBtKSwgYWRqdXN0aW5nIGZvciBzZXgsIGFnZSwgYW5kIHNvY2lvZWNvbm9taWMgc3RhdHVzIChTRVMpLiAKCmBgYHtyfQpzdW1tYXJ5KG1vZGVsX21pdGlnYXRpb24pCmBgYAo8ZGl2IHN0eWxlPSJjb2xvcjogZ3JlZW47IGZvbnQtZmFtaWx5OiAnR2VvcmdpYScsIHNlcmlmOyBmb250LXNpemU6IDE2cHg7IGZvbnQtd2VpZ2h0OiBub3JtYWw7Ij4KICA8c3Ryb25nPkludGVycHJldGF0aW9uPC9zdHJvbmc+PGJyPiBBIDHCsEMgaW5jcmVhc2UgaW4gbWVhbiBkYXl0aW1lIHRlbXBlcmF0dXJlIGlzIGFzc29jaWF0ZWQgd2l0aCBhIDAuOTYgYnBtIGluY3JlYXNlIGluIG1lYW4gaGVhcnQgcmF0ZSwgYWRqdXN0aW5nIGZvciBzZXgsIGFnZSwgYW5kIHNvY2lvZWNvbm9taWMgc3RhdHVzIChTRVMpLiBGb3IgZXhhbXBsZSwgYSA1wrBDIGluY3JlYXNlIHdvdWxkIGNvcnJlc3BvbmQgdG8gYW4gYXBwcm94aW1hdGUgNC44IGJwbSBpbmNyZWFzZSBpbiBoZWFydCByYXRlLiBUaGUgbW9kZWwgZXhwbGFpbnMgYXBwcm94aW1hdGVseSA2LjglIG9mIHRoZSB2YXJpYW5jZSBpbiBoZWFydCByYXRlLiBUaGUgcmVzaWR1YWwgc3RhbmRhcmQgZXJyb3IgaXMgMTEuNTYsIHN1Z2dlc3RpbmcgdGhhdCBwcmVkaWN0ZWQgaGVhcnQgcmF0ZSB2YWx1ZXMgZGV2aWF0ZSBvbiBhdmVyYWdlIGJ5IGFyb3VuZCDCsTEyIGJwbSBmcm9tIG9ic2VydmVkIHZhbHVlcy4gT3ZlcmFsbCwgdGhlIG1vZGVsIGlzIHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQgKHAgJmx0OyAwLjAwMSkuCjwvZGl2PgoKTm93IHdlIHdpbGwgYXNzZXNzIGVmZmVjdCBtb2RpZmljYXRpb24gYWNyb3NzIHRlcnRpbGVzLgoKYGBge3J9CmxpYnJhcnkoZ2dlZmZlY3RzKQpgYGAKTG9hZCB0aGUgImdnZWZmZWN0cyIgcGFja2FnZSB0byBleHRyYWN0IHByZWRpY3RlZCAobWFyZ2luYWwpIGVmZmVjdHMgZnJvbSByZWdyZXNzaW9uIG1vZGVscywgaW5jbHVkaW5nIG1vZGVscyB3aXRoIGludGVyYWN0aW9uIHRlcm1zLiBUaGVzZSBwcmVkaWN0aW9ucyBhcmUgYWRqdXN0ZWQgZm9yIGFueSBjb25mb3VuZGVycyBpbmNsdWRlZCBpbiB0aGUgbW9kZWwuCgpgYGB7cn0KbW9kZWxfbmR2aV9pbnRlcmFjdGlvbiA8LSBsbShtZWFuX2hyIH4gbWVhbl90ZW1wICogbmR2aV90ZXJ0aWxlICsgc2V4ICsgYWdlICsgc2VzLCBkYXRhID0gTWl0aWdhdGlvbikKbW9kZWxfdGNfaW50ZXJhY3Rpb24gPC0gbG0obWVhbl9ociB+IG1lYW5fdGVtcCAqIHRjX3RlcnRpbGUgKyBzZXggKyBhZ2UgKyBzZXMsIGRhdGEgPSBNaXRpZ2F0aW9uKQpgYGAKRml0IGxpbmVhciByZWdyZXNzaW9uIG1vZGVscyB3aXRoIGFuIGludGVyYWN0aW9uIHRlcm0uCgpgYGB7cn0KcHJlZF9uZHZpIDwtIGdncHJlZGljdChtb2RlbF9uZHZpX2ludGVyYWN0aW9uLCB0ZXJtcyA9IGMoIm1lYW5fdGVtcCIsICJuZHZpX3RlcnRpbGUiKSkKcHJlZF90YyA8LSBnZ3ByZWRpY3QobW9kZWxfdGNfaW50ZXJhY3Rpb24sIHRlcm1zID0gYygibWVhbl90ZW1wIiwgInRjX3RlcnRpbGUiKSkKYGBgClRoaXMgZnVuY3Rpb24gY2FsY3VsYXRlcyBtb2RlbC1wcmVkaWN0ZWQgaGVhcnQgcmF0ZXMgYWNyb3NzIGEgcmFuZ2Ugb2YgdGVtcGVyYXR1cmUgdmFsdWVzLCBzZXBhcmF0ZWx5IGZvciBlYWNoIHRlcnRpbGUuCgpgYGB7cn0KCmxpYnJhcnkocGF0Y2h3b3JrKQoKcGxvdF9uZHZpIDwtIHBsb3QocHJlZF9uZHZpKSArCiAgbGFicygKICAgIHRpdGxlID0gIkVmZmVjdCBNb2RpZmljYXRpb24gYnkgTkRWSSIsCiAgICB4ID0gIk1lYW4gRGF5dGltZSBUZW1wZXJhdHVyZSAowrBDKSIsCiAgICB5ID0gIlByZWRpY3RlZCBNZWFuIEhlYXJ0IFJhdGUgKGJwbSkiLAogICAgY29sb3IgPSAiTkRWSSIKICApICsKICB0aGVtZV9taW5pbWFsKCkKCnBsb3RfdGMgPC0gcGxvdChwcmVkX3RjKSArCiAgbGFicygKICAgIHRpdGxlID0gIkVmZmVjdCBNb2RpZmljYXRpb24gYnkgVHJlZSBDb3ZlciIsCiAgICB4ID0gIk1lYW4gRGF5dGltZSBUZW1wZXJhdHVyZSAowrBDKSIsCiAgICB5ID0gIlByZWRpY3RlZCBNZWFuIEhlYXJ0IFJhdGUgKGJwbSkiLAogICAgY29sb3IgPSAiVHJlZSBDb3ZlciIKICApICsKICB0aGVtZV9taW5pbWFsKCkKCnBsb3RfbmR2aSArIHBsb3RfdGMKCmBgYAo8ZGl2IHN0eWxlPSJjb2xvcjogZ3JlZW47IGZvbnQtZmFtaWx5OiAnR2VvcmdpYScsIHNlcmlmOyBmb250LXNpemU6IDE2cHg7IGZvbnQtd2VpZ2h0OiBub3JtYWw7Ij4KICA8c3Ryb25nPkludGVycHJldGF0aW9uPC9zdHJvbmc+PGJyPgpUaGUgcGxvdHMgaWxsdXN0cmF0ZSB0aGF0IHRoZSBhc3NvY2lhdGlvbiBiZXR3ZWVuIG1lYW4gZGF5dGltZSB0ZW1wZXJhdHVyZSBhbmQgaGVhcnQgcmF0ZSBpcyBtb2RpZmllZCBieSBzdXJyb3VuZGluZyB2ZWdldGF0aW9uLiBJbiBib3RoIHRoZSBORFZJIGFuZCB0cmVlIGNvdmVyIG1vZGVscywgaGlnaGVyIHZlZ2V0YXRpb24gbGV2ZWxzIGFyZSBhc3NvY2lhdGVkIHdpdGggYSBwcm9ncmVzc2l2ZWx5IHdlYWtlciB0ZW1wZXJhdHVyZeKAk2hlYXJ0IHJhdGUgcmVsYXRpb25zaGlwIGFjcm9zcyB0ZXJ0aWxlcy4gVGhpcyBwYXR0ZXJuIHN1Z2dlc3RzIHRoYXQgaW5jcmVhc2VkIHZlZ2V0YXRpb24gbWF5IGF0dGVudWF0ZSB0aGUgcGh5c2lvbG9naWNhbCByZXNwb25zZSB0byBoZWF0IGV4cG9zdXJlLgoKSG93ZXZlciwgc3VjaCBhdHRlbnVhdGlvbiBpcyBtb3JlIHByb25vdW5jZWQgaW4gdGhlIGNhc2Ugb2YgdHJlZSBjb3Zlci4gSW4gYXJlYXMgd2l0aCBoaWdoIHRyZWUgY292ZXIsIHRoZSBzbG9wZSBpcyBhbG1vc3QgZmxhdCwgaW5kaWNhdGluZyBzdWJzdGFudGlhbCBtaXRpZ2F0aW9uIG9mIGhlYXQgZWZmZWN0cy4gSW4gY29udHJhc3QsIHRoZSBtaXRpZ2F0aW9uIG9ic2VydmVkIGZvciBoaWdoIE5EVkkgaXMgbW9yZSBtb2Rlc3QuIFRoZXNlIHJlc3VsdHMgc3VnZ2VzdCB0aGF0LCBhbHRob3VnaCBib3RoIG1ldHJpY3MgcHJvdmlkZSBzb21lIHByb3RlY3Rpb24sIHRyZWUgY292ZXIgaXMgbW9yZSBlZmZlY3RpdmUgaW4gbWl0aWdhdGluZyB0aGUgcGh5c2lvbG9naWNhbCBpbXBhY3RzIG9mIGhlYXQuIAoKCjwvZGl2PgoKWyoqRVhFUkNJU0UgMjoqKiBSZXN0b3JhdGlvbiBwYXRod2F5XXtzdHlsZT0iZm9udC1zaXplOjI0cHg7IHRleHQtZGVjb3JhdGlvbjp1bmRlcmxpbmU7Y29sb3I6Z3JlZW47In0KClRoaXMgZXhlcmNpc2UgZXhhbWluZXMgaG93IGRpZmZlcmVudCBncmVlbm5lc3MgbWV0cmljcyBpbmZsdWVuY2UgaGVhbHRoIHRocm91Z2ggdGhlIHJlc3RvcmF0aW9uIHBhdGh3YXkuIFRoZSByZXN0b3JhdGlvbiBwYXRod2F5IGRlc2NyaWJlcyBob3cgZXhwb3N1cmUgdG8gZ3JlZW5uZXNzIGltcHJvdmVzIGhlYWx0aCB0aHJvdWdoIHR3byBtYWpvciB0aGVvcmllczogdGhlICoqQXR0ZW50aW9uIFJlc3RvcmF0aW9uIFRoZW9yeSAoQVJUKSoqIGFuZCB0aGUgKipTdHJlc3MgUmVkdWN0aW9uIFRoZW9yeSAoU1JUKSoqLiBUaGUgU1JUIGFuZCBBUlQgYXJlIGludGVyY29ubmVjdGVkLCBncm91bmRlZCBpbiBiaW9waGlsaWMgcHJpbmNpcGxlcywgZW1waGFzaXppbmcgdGhlIGlubmF0ZSBodW1hbiBjb25uZWN0aW9uIHRvIG5hdHVyZS4gQWNjb3JkaW5nIHRvIHRoZSBiaW9waGlsaWEgaHlwb3RoZXNpcywgaHVtYW5zIGhhdmUgYW4gZXZvbHV0aW9uYXJ5IHRlbmRlbmN5IHRvIHNlZWsgY29ubmVjdGlvbnMgd2l0aCBvdGhlciBmb3JtcyBvZiBsaWZlIChXaWxzb24sIDE5ODYpLgoKKipERVNDUklQVElPTioqCgpJbiB0aGlzIGV4ZXJjaXNlLCB5b3Ugd2lsbCBhbmFseXplIGdlbmVyYXRlZCBkYXRhIGZyb20gNSwwMDAgcGFydGljaXBhbnRzIHRvIGV4YW1pbmUgaG93IGdyZWVubmVzcyBleHBvc3VyZSByZWxhdGVzIHRvIHBoeXNpb2xvZ2ljYWwgc3RyZXNzLCBtZWFzdXJlZCB0aHJvdWdoIGNvcnRpc29sIGxldmVscy4gR3JlZW5uZXNzIGlzIGFzc2Vzc2VkIHVzaW5nIE5EVkkgd2l0aGluIGEgNTAwLW1ldGVyIGJ1ZmZlciBhcm91bmQgdGhlIGhvbWUsIHdoaWxlIHdlZWtseSB0aW1lIHNwZW50IGluIGdyZWVuIHNwYWNlcyAobWludXRlcykgaXMgb2JqZWN0aXZlbHkgbWVhc3VyZWQgdXNpbmcgaW5kaXZpZHVhbCB0cmFja2luZyBkZXZpY2VzLgoKYGBge3J9ClJlc3RvcmF0aW9uIDwtIHJlYWRfY3N2KCJSZXN0b3JhdGlvbi5jc3YiKQpgYGAKTG9hZCB0aGUgc3ludGhldGljIGRhdGFzZXQgdGl0bGVkICJSZXN0b3JhdGlvbi5jc3YiLgoKYGBge3J9CnN0cihSZXN0b3JhdGlvbikKYGBgCkV4YW1pbmUgdGhlIHN0cnVjdHVyZSBvZiB0aGUgZGF0YXNldC4gVGhlICJSZXN0b3JhdGlvbiIgZGF0YXNldCBzaW11bGF0ZXMgZGF0YSBmb3IgNSwwMDAgYWR1bHQgcGFydGljaXBhbnRzIHdpdGggdGhlIGZvbGxvd2luZyB2YXJpYWJsZXM6CgotICAgKippZCoqOiBJbmRlbnRpZmljYXRpb24gbnVtYmVyCi0gICAqKm5kdmkqKjogTm9ybWFsaXplZCBEaWZmZXJlbmNlIFZlZ2V0YXRpb24gSW5kZXggKE5EVkkpIHdpdGhpbiBhIDUwMC1tIGJ1ZmZlciBvZiB0aGUgcmVzaWRlbmNlCi0gICAqKmdyZWVuX21pbnV0ZXMqKjogTWVhbiB3ZWVrbHkgdGltZSBzcGVudCBpbiBncmVlbiBzcGFjZXMgKG1pbnV0ZXMpCi0gICAqKmNvcnRpc29sKio6IEhhaXIgY29ydGlzb2wgbWVhc3VyZXMgKHBnL21nKQotICAgKipzZXgqKjogU2V4IChGZW1hbGUgb3IgTWFsZSkKLSAgICoqYWdlKio6IEFnZSAoeWVhcnMpCi0gICAqKnNlcyoqOiBTb2Npb2Vjb25vbWljIHN0YXR1cywgKEkgKGhpZ2hlc3QpIHRvIFYgKGxvd2VzdCkpCgoKYGBge3J9ClJlc3RvcmF0aW9uJHNleCA8LSBmYWN0b3IoUmVzdG9yYXRpb24kc2V4LCBsYWJlbHMgPSBjKCJGZW1hbGUiLCAiTWFsZSIpKQpSZXN0b3JhdGlvbiRzZXMgPC0gZmFjdG9yKFJlc3RvcmF0aW9uJHNlcywgbGFiZWxzID0gYygiSSIsICJJSSIsICJJSUkiLCAiSVYiLCAiViIpKQpgYGAKUmVjb2RlIGNhdGVnb3JpY2FsIHZhcmlhYmxlcyBpbiB0aGUgIlJlc3RvcmF0aW9uIiBkYXRhc2V0IGFzIGZhY3Rvci4KCmBgYHtyfQpza2ltKFJlc3RvcmF0aW9uWywgYygibmR2aSIsICJncmVlbl9taW51dGVzIiwgImNvcnRpc29sIildKQpgYGAKQ2hlY2sgdGhlIGRpc3RyaWJ1dGlvbiBvZiB0aGUgZXhwb3N1cmUgYW5kIG91dGNvbWUgdmFyaWFibGVzLiAKCmBgYHtyfQptb2RlbF9uZHZpIDwtIGxtKGNvcnRpc29sIH4gbmR2aSArIHNleCArIGFnZSArIHNlcywgZGF0YSA9IFJlc3RvcmF0aW9uKQpgYGAKRml0IGEgbGluZWFyIHJlZ3Jlc3Npb24gbW9kZWwgdG8gZXhhbWluZSB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gTkRWSSAoZXhwb3N1cmUpIGFuZCBoYWlyIGNvcnRpc29sIGxldmVscyAob3V0Y29tZSksIGFkanVzdGluZyBmb3IgcG90ZW50aWFsIGNvbmZvdW5kZXJzIChzZXgsIGFnZSwgc2VzKS4gCgpgYGB7cn0Kc3VtbWFyeShtb2RlbF9uZHZpKQpgYGAKPGRpdiBzdHlsZT0iY29sb3I6IGdyZWVuOyBmb250LWZhbWlseTogJ0dlb3JnaWEnLCBzZXJpZjsgZm9udC1zaXplOiAxNnB4OyBmb250LXdlaWdodDogbm9ybWFsOyI+CiAgPHN0cm9uZz5JbnRlcnByZXRhdGlvbjwvc3Ryb25nPjxicj4gQSAxLXVuaXQgaW5jcmVhc2UgaW4gTkRWSSAoZnJvbSAwIHRvIDEpIGlzIGFzc29jaWF0ZWQgd2l0aCBhIDIzLjUtdW5pdCBkZWNyZWFzZSBpbiBoYWlyIGNvcnRpc29sLCBhZGp1c3RpbmcgZm9yIG90aGVyIHZhcmlhYmxlcy4gVGhpcyBpcyBkaWZmaWN1bHQgdG8gaW50ZXJwcmV0LiAKVXNpbmcgdGhlIElRUiBpbnN0ZWFkLCBhbGxvd3MgdG8gaW50ZXJwcmV0IHRoZSBlZmZlY3Qgb2YgTkRWSSBpbiB0ZXJtcyBvZiBhIHR5cGljYWwsIHJlYWxpc3RpYyBjaGFuZ2UgaW4gZXhwb3N1cmUsIG1ha2luZyB0aGUgcmVzdWx0cyBjbGVhcmVyLgo8L2Rpdj4KCgpgYGB7cn0KaXFyX25kdmkgPC0gSVFSKFJlc3RvcmF0aW9uJG5kdmkpClJlc3RvcmF0aW9uJG5kdmlfaXFyIDwtIFJlc3RvcmF0aW9uJG5kdmkvaXFyX25kdmkKbW9kZWxfbmR2aV9pcXIgPC0gbG0oY29ydGlzb2wgfiBuZHZpX2lxciArIHNleCArIGFnZSArIHNlcywgZGF0YSA9IFJlc3RvcmF0aW9uKQpgYGAKU3RhbmRhcml6ZSBORFZJIGRpdmlkaW5nIGl0IGJ5IGl0cyBJUVIgdG8gbWFrZSB0aGUgZWZmZWN0IHNpemUgbW9yZSBpbnRlcnByZXRhYmxlLCB0aGVuIG1vZGVsIGl0cyBhc3NvY2lhdGlvbiB3aXRoIGhhaXIgY29ydGlzb2wsIGFkanVzdGluZyBmb3Iga2V5IGNvdmFyaWF0ZXMuCgpgYGB7cn0Kc3VtbWFyeShtb2RlbF9uZHZpX2lxcikKYGBgCjxkaXYgc3R5bGU9ImNvbG9yOiBncmVlbjsgZm9udC1mYW1pbHk6ICdHZW9yZ2lhJywgc2VyaWY7IGZvbnQtc2l6ZTogMTZweDsgZm9udC13ZWlnaHQ6IG5vcm1hbDsiPgogIDxzdHJvbmc+SW50ZXJwcmV0YXRpb248L3N0cm9uZz48YnI+IEEgMSBJUVIgaW5jcmVhc2UgaW4gTkRWSSBpcyBhc3NvY2lhdGVkIHdpdGggYSA0LjMxIHBnL21nIGRlY3JlYXNlIGluIGNvcnRpc29sLCBhZGp1c3RpbmcgZm9yIHNleCwgYWdlLCBhbmQgU0VTLiBUaGUgbW9kZWwgZXhwbGFpbnMgNi40JSBvZiB0aGUgdmFyaWFuY2UgaW4gaGFpciBjb3J0aXNvbCBsZXZlbHMuIFRoZSByZXNpZHVhbCBzdGFuZGFyZCBlcnJvciBvZiAyNS4yOSBpcyByZWxhdGl2ZWx5IGhpZ2gsIG1lYW5pbmcgdGhhdCBwcmVkaWN0aW9ucyBmcm9tIHRoZSBtb2RlbCBvZnRlbiBkZXZpYXRlIHN1YnN0YW50aWFsbHkgZnJvbSBhY3R1YWwgaGFpciBjb3J0aXNvbCB2YWx1ZXMuIE92ZXJhbGwsIHRoZSBtb2RlbCBpcyBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50IChwIDwgMC4wMDEpLgo8L2Rpdj4KCmBgYHtyfQptb2RlbF90aW1lIDwtIGxtKGNvcnRpc29sIH4gZ3JlZW5fbWludXRlcyArIHNlcyArIGFnZSArIHNleCwgZGF0YSA9IFJlc3RvcmF0aW9uKQpgYGAKRml0IGEgbGluZWFyIHJlZ3Jlc3Npb24gbW9kZWwgdG8gZXhhbWluZSB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gaGFpciBjb3J0aXNvbCBsZXZlbHMgKG91dGNvbWUpIGFuZCBtZWFuIHdlZWtseSB0aW1lIHNwZW50IGluIGdyZWVuIHNwYWNlcyAoZXhwb3N1cmUpLCBhZGp1c3RpbmcgZm9yIHBvdGVudGlhbCBjb25mb3VuZGVycy4gCgpgYGB7cn0Kc3VtbWFyeShtb2RlbF90aW1lKQpgYGAKPGRpdiBzdHlsZT0iY29sb3I6IGdyZWVuOyBmb250LWZhbWlseTogJ0dlb3JnaWEnLCBzZXJpZjsgZm9udC1zaXplOiAxNnB4OyBmb250LXdlaWdodDogbm9ybWFsOyI+CiAgPHN0cm9uZz5JbnRlcnByZXRhdGlvbjwvc3Ryb25nPjxicj4KQSAxLW1pbnV0ZSBpbmNyZWFzZSBpbiB0aGUgbWVhbiB3ZWVrbHkgdGltZSBzcGVudCBpbiBncmVlbiBzcGFjZXMgaXMgYXNzb2NpYXRlZCB3aXRoIGEgMC4xNSBwZy9tZyBkZWNyZWFzZSBpbiBoYWlyIGNvcnRpc29sLCBhZGp1c3RpbmcgZm9yIFNFUywgYWdlLCBhbmQgc2V4LiBGb3IgZXhhbXBsZSwgYW4gaW5jcmVhc2Ugb2YgMzAgbWludXRlcyBwZXIgd2VlayB3b3VsZCBjb3JyZXNwb25kIHRvIGEgNC41IHBnL21nIHJlZHVjdGlvbiBpbiBjb3J0aXNvbCBsZXZlbHMuIFRoZSBtb2RlbCBleHBsYWlucyA3LjMlIG9mIHRoZSB2YXJpYW5jZSBpbiBoYWlyIGNvcnRpc29sIGxldmVscy4gVGhlIHJlc2lkdWFsIHN0YW5kYXJkIGVycm9yIGlzIDI1LjE2LCBpbmRpY2F0aW5nIHRoYXQgcHJlZGljdGVkIGNvcnRpc29sIHZhbHVlcyBvZnRlbiBkZXZpYXRlIG5vdGFibHkgZnJvbSBvYnNlcnZlZCB2YWx1ZXMuIE92ZXJhbGwsIHRoZSBtb2RlbCBpcyBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50IChwIDwgMC4wMDEpLgo8L2Rpdj4KCgpgYGB7cn0KbGlicmFyeShwYXRjaHdvcmspCmBgYApMb2FkIHRoZSByZXF1aXJlZCBwYWNrYWdlIHRvIGNvbWJpbmUgZ2dwbG90IG9iamVjdHMuCgpgYGB7cn0KcDEgPC0gZ2dwbG90KFJlc3RvcmF0aW9uLCBhZXMoeCA9IG5kdmksIHkgPSBjb3J0aXNvbCkpICsKICBnZW9tX3BvaW50KGFscGhhID0gMC4zLCBjb2xvciA9ICIjMTQ1QTMyIikgKwogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIGNvbG9yID0gIiMyN0FFNjAiLCBmaWxsID0gIiNBQkVCQzYiKSArCiAgbGFicygKICAgIHRpdGxlID0gIk5EVkkgdnMuIEhhaXIgQ29ydGlzb2wiLAogICAgeCA9ICJORFZJIChSZXNpZGVudGlhbCBHcmVlbm5lc3MpIiwKICAgIHkgPSAiSGFpciBDb3J0aXNvbCAocGcvbWcpIgogICkgKwogIHRoZW1lX21pbmltYWwoYmFzZV9zaXplID0gMTApCmBgYApDcmVhdGUgYSBzY2F0dGVycGxvdCBzaG93aW5nIHRoZSBhc3NvY2lhdGlvbiBiZXR3ZWVuIE5EVkkgYW5kIGhhaXIgY29ydGlzb2wgbGV2ZWxzLgoKYGBge3J9CnAyIDwtIGdncGxvdChSZXN0b3JhdGlvbiwgYWVzKHggPSBncmVlbl9taW51dGVzLCB5ID0gY29ydGlzb2wpKSArCiAgZ2VvbV9wb2ludChhbHBoYSA9IDAuMywgY29sb3IgPSAiIzJDM0U1MCIpICsKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBjb2xvciA9ICIjMjk4MEI5IiwgZmlsbCA9ICIjODVDMUU5IikgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJHcmVlbiBTcGFjZSBUaW1lIHZzLiBIYWlyIENvcnRpc29sIiwKICAgIHggPSAiR3JlZW4gU3BhY2UgVGltZSAobWludXRlcy93ZWVrKSIsCiAgICB5ID0gIkhhaXIgQ29ydGlzb2wgKHBnL21nKSIKICApICsKICB0aGVtZV9taW5pbWFsKGJhc2Vfc2l6ZSA9IDEwKQpgYGAKQ3JlYXRlIGEgc2Vjb25kIHNjYXR0ZXJwbG90IG9uIHRoZSBhc3NvY2lhdGlvbiBiZXR3ZWVuIG1lYW4gd2Vla2x5IHRpbWUgc3BlbnQgaW4gZ3JlZW4gc3BhY2VzIGFuZCBoYWlyIGNvcnRpc29sIGxldmVscy4KCmBgYHtyfQpjb21iaW5lZF9wbG90IDwtIHAxICsgcDIKY29tYmluZWRfcGxvdApgYGAKQ29tYmluZSBwbG90cyBmb3IgY29tcGFyaXNvbiB1c2luZyBwYXRjaHdvcmsuCgo8ZGl2IHN0eWxlPSJjb2xvcjogZ3JlZW47IGZvbnQtZmFtaWx5OiAnR2VvcmdpYScsIHNlcmlmOyBmb250LXNpemU6IDE2cHg7IGZvbnQtd2VpZ2h0OiBub3JtYWw7Ij4KICA8c3Ryb25nPkludGVycHJldGF0aW9uPC9zdHJvbmc+PGJyPiBXaGlsZSBib3RoICJORFZJIiBhbmQgIkdyZWVuIFNwYWNlIFRpbWUiIGFyZSBzaWduaWZpY2FudGx5IGFzc29jaWF0ZWQgd2l0aCBsb3dlciBoYWlyIGNvcnRpc29sLCAiR3JlZW4gU3BhY2UgVGltZSIgc2hvd3MgYSBzdHJvbmdlciBzdGF0aXN0aWNhbCBhc3NvY2lhdGlvbiBhbmQgc2xpZ2h0bHkgYmV0dGVyIG1vZGVsIGZpdC4gVGhpcyBzdWdnZXN0cyB0aGF0IHdoaWxlIE5EVkkgaXMgYSB3aWRlbHkgYXZhaWxhYmxlIGFuZCBzdHJhaWdodGZvcndhcmQgZ3JlZW5uZXNzIG1ldHJpYywgdGhlIHJlc3RvcmF0aW9uIHBhdGh3YXkgbGlrZWx5IGludm9sdmVzIGRpcmVjdCBpbnRlcmFjdGlvbiB3aXRoIG5hdHVyZS4gVGhlcmVmb3JlLCBzdHVkaWVzIHNob3VsZCBjb25zaWRlciBub3Qgb25seSBzcGF0aWFsIGF2YWlsYWJpbGl0eSBvZiBncmVlbm5lc3MgYnV0IGFsc28gdGhlIGZyZXF1ZW5jeSBhbmQgZHVyYXRpb24gb2YgaW5kaXZpZHVhbCBleHBvc3VyZS4KPC9kaXY+CgpbKipFWEVSQ0lTRSAzOioqIEluc3RvcmF0aW9uIHBhdGh3YXlde3N0eWxlPSJmb250LXNpemU6MjRweDsgdGV4dC1kZWNvcmF0aW9uOnVuZGVybGluZTtjb2xvcjpncmVlbjsifQoKVGhpcyBleGVyY2lzZSBleGFtaW5lcyBob3cgZGlmZmVyZW50IGdyZWVubmVzcyBtZXRyaWNzIGluZmx1ZW5jZSBoZWFsdGggdGhyb3VnaCB0aGUgaW5zdG9yYXRpb24gcGF0aHdheS4gVGhlIGluc3RvcmF0aW9uIG9yIGNhcGFjaXR5IGJ1aWxkaW5nIHBhdGh3YXksIGhpZ2hsaWdodHMgaG93IG5hdHVyYWwgZW52aXJvbm1lbnRzIHByb21vdGUgaGVhbHRoLXJlbGF0ZWQgYmVoYXZpb3JzIGJ5IGVuY291cmFnaW5nIHBoeXNpY2FsIGFjdGl2aXR5IGFuZCBzb2NpYWwgY29oZXNpb24uCgpHcmVlbiBzcGFjZXMgb2Z0ZW4gcHJvdmlkZSBhIHNlY3VyZSwgYWNjZXNzaWJsZSwgYW5kIGF0dHJhY3RpdmUgc2V0dGluZyBpbiB3aGljaAp0byBiZSBwaHlzaWNhbGx5IGFjdGl2ZS4gSW4gdGhpcyByZWdhcmQsIG51bWVyb3VzIHN0dWRpZXMgaGF2ZSBmb3VuZCBwb3NpdGl2ZSBhc3NvY2lhdGlvbnMgYmV0d2VlbiBpbmNyZWFzZWQgZXhwb3N1cmUgdG8gZ3JlZW4gZW52aXJvbm1lbnRzIGFuZCBoaWdoZXIgbGV2ZWxzIG9mIHBoeXNpY2FsIGFjdGl2aXR5IChHaWFuZnJlZGkgZXQgYWwuLCAyMDIxKSwgd2hpY2gsIGluIHR1cm4sIGlzIGxpbmtlZCB0byBpbXByb3ZlZCBwaHlzaWNhbCAoQnVsbCBldCBhbC4sIDIwMjApIGFuZCBtZW50YWwgaGVhbHRoIChSb2RyaWd1ZXotQXlsbG9uIGV0IGFsLiwgMjAxOSkuCgoqKkRFU0NSSVBUSU9OKioKCkluIHRoaXMgZXhlcmNpc2UsIHlvdSB3aWxsIGFuYWx5emUgZ2VuZXJhdGVkIGRhdGEgZnJvbSA1LDAwMCBwYXJ0aWNpcGFudHMgdG8gZXhhbWluZSBob3cgcHJveGltaXR5IHRvIGdyZWVuIHNwYWNlcyByZWxhdGVzIHRvIHBoeXNpY2FsIGFjdGl2aXR5LCBtZWFzdXJlZCBhcyB3ZWVrbHkgbWludXRlcyB1c2luZyBpbmRpdmlkdWFsIHRyYWNraW5nIGRldmljZXMuIEdyZWVubmVzcyBleHBvc3VyZSBpcyBhc3Nlc3NlZCB1c2luZyB0d28gZGlmZmVyZW50IGRpc3RhbmNlIG1lYXN1cmVzIGJhc2VkIG9uIHRoZSByZXNpZGVudGlhbCBhZGRyZXNzOiAKCi0gICBTdHJhaWdodC1saW5lIGRpc3RhbmNlIHRvIHRoZSBjbG9zZXN0IGdyZWVuIHNwYWNlIChpbiBtZXRlcnMpCi0gICBOZXR3b3JrIGRpc3RhbmNlIHRvIHRoZSBjbG9zZXN0IGdyZWVuIHNwYWNlIChpbiBtZXRlcnMpCgoKYGBge3J9Ckluc3RvcmF0aW9uIDwtIHJlYWRfY3N2KCJJbnN0b3JhdGlvbi5jc3YiKQpgYGAKTG9hZCB0aGUgc3ludGhldGljIGRhdGFzZXQgdGl0bGVkICJJbnN0b3JhdGlvbi5jc3YiLgoKYGBge3J9CnN0cihJbnN0b3JhdGlvbikKYGBgCkV4YW1pbmUgdGhlIHN0cnVjdHVyZSBvZiB0aGUgZGF0YXNldC4gVGhlICJJbnN0b3JhdGlvbiIgZGF0YXNldCBzaW11bGF0ZXMgZGF0YSBmb3IgNSwwMDAgYWR1bHQgcGFydGljaXBhbnRzIHdpdGggdGhlIGZvbGxvd2luZyB2YXJpYWJsZXM6CgotICAgKippZCoqOiBJbmRlbnRpZmljYXRpb24gbnVtYmVyCi0gICAqKnN0cmFpZ2h0X2Rpc3RhbmNlKio6IFN0cmFpZ2h0LWxpbmUgZGlzdGFuY2UgdG8gdGhlIG5lYXJlc3QgZ3JlZW4gc3BhY2UgKG1ldGVycykgYmFzZWQgb24gdGhlIHJlc2lkZW5jZQotICAgKipuZXR3b3JrX2Rpc3RhbmNlKio6IE5ldHdvcmsgZGlzdGFuY2UgdG8gdGhlIG5lYXJlc3QgZ3JlZW4gc3BhY2UgKG1ldGVycykgYmFzZWQgb24gdGhlIHJlc2lkZW5jZQotICAgKip3ZWVrbHlfcGEqKjogV2Vla2x5IHBoeXNpY2FsIGFjdGl2aXR5IChtaW51dGVzKQotICAgKipzZXgqKjogU2V4IChGZW1hbGUgb3IgTWFsZSkKLSAgICoqYWdlKio6IEFnZSAoeWVhcnMpCi0gICAqKnNlcyoqOiBTb2Npb2Vjb25vbWljIHN0YXR1cywgKEkgKGhpZ2hlc3QpIHRvIFYgKGxvd2VzdCkpCgoKYGBge3J9Ckluc3RvcmF0aW9uJHNleCA8LSBmYWN0b3IoSW5zdG9yYXRpb24kc2V4LCBsYWJlbHMgPSBjKCJGZW1hbGUiLCAiTWFsZSIpKQpJbnN0b3JhdGlvbiRzZXMgPC0gZmFjdG9yKEluc3RvcmF0aW9uJHNlcywgbGFiZWxzID0gYygiSSIsICJJSSIsICJJSUkiLCAiSVYiLCAiViIpKQpgYGAKUmVjb2RlIGNhdGVnb3JpY2FsIHZhcmlhYmxlcyBpbiB0aGUgIkluc3RvcmF0aW9uIiBkYXRhc2V0IGFzIGZhY3Rvci4KCmBgYHtyfQpza2ltKEluc3RvcmF0aW9uWywgYygic3RyYWlnaHRfZGlzdGFuY2UiLCAibmV0d29ya19kaXN0YW5jZSIsICJ3ZWVrbHlfcGEiKV0pCmBgYApDaGVjayB0aGUgZGlzdHJpYnV0aW9uIG9mIHRoZSBleHBvc3VyZSBhbmQgb3V0Y29tZSB2YXJpYWJsZXMuIAoKYGBge3J9Cm1vZGVsX3N0cmFpZ2h0IDwtIGxtKHdlZWtseV9wYSB+IHN0cmFpZ2h0X2Rpc3RhbmNlICsgc2V4ICsgYWdlICsgc2VzLCBkYXRhID0gSW5zdG9yYXRpb24pCmBgYApGaXQgYSBsaW5lYXIgcmVncmVzc2lvbiBtb2RlbCB0byBleGFtaW5lIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiAqKnN0cmFpZ2h0LWxpbmUgZGlzdGFuY2UgdG8gdGhlIG5lYXJlc3QgZ3JlZW4gc3BhY2UqKiAoZXhwb3N1cmUpIGFuZCAqKndlZWtseSBwaHlzaWNhbCBhY3Rpdml0eSB0aW1lKiogKG91dGNvbWUpLCBhZGp1c3RpbmcgZm9yIHBvdGVudGlhbCBjb25mb3VuZGVycyAoc2V4LCBhZ2UsIHNlcykuIAoKYGBge3J9CnN1bW1hcnkobW9kZWxfc3RyYWlnaHQpCmBgYAo8ZGl2IHN0eWxlPSJjb2xvcjogZ3JlZW47IGZvbnQtZmFtaWx5OiAnR2VvcmdpYScsIHNlcmlmOyBmb250LXNpemU6IDE2cHg7IGZvbnQtd2VpZ2h0OiBub3JtYWw7Ij4KICA8c3Ryb25nPkludGVycHJldGF0aW9uPC9zdHJvbmc+PGJyPiBBIDEwMC1tZXRlciBpbmNyZWFzZSBpbiBzdHJhaWdodC1saW5lIGRpc3RhbmNlIHRvIHRoZSBuZWFyZXN0IGdyZWVuIHNwYWNlIGlzIGFzc29jaWF0ZWQgd2l0aCBhIDIuMzctbWludXRlIGRlY3JlYXNlIGluIHdlZWtseSBwaHlzaWNhbCBhY3Rpdml0eSwgYWRqdXN0aW5nIGZvciBzZXgsIGFnZSwgYW5kIHNvY2lvZWNvbm9taWMgc3RhdHVzLiBUaGUgbW9kZWwgZXhwbGFpbnMgMy42JSBvZiB0aGUgdmFyaWFuY2UgaW4gd2Vla2x5IHBoeXNpY2FsIGFjdGl2aXR5LiBUaGUgcmVzaWR1YWwgc3RhbmRhcmQgZXJyb3IgaW5kaWNhdGVzIGEgc3Vic3RhbnRpYWwgdW5leHBsYWluZWQgdmFyaWFiaWxpdHkgb2YgYXJvdW5kIDMwIG1pbnV0ZXMuIEFsdGhvdWdoIHRoZSBhc3NvY2lhdGlvbiBpcyBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50IChwIDwgMC4wMDEpLCB0aGUgb3ZlcmFsbCBlZmZlY3Qgc2l6ZSBpcyBzbWFsbCwgYW5kIHRoZSBleHBsYW5hdG9yeSBwb3dlciBpcyBsaW1pdGVkLiAKCjwvZGl2PgoKYGBge3J9Cm1vZGVsX25ldHdvcmsgPC0gbG0od2Vla2x5X3BhIH4gbmV0d29ya19kaXN0YW5jZSArIHNleCArIGFnZSArIHNlcywgZGF0YSA9IEluc3RvcmF0aW9uKQpgYGAKRml0IGEgbGluZWFyIHJlZ3Jlc3Npb24gbW9kZWwgdG8gZXhhbWluZSB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gKipuZXR3b3JrIGRpc3RhbmNlIHRvIHRoZSBuZWFyZXN0IGdyZWVuIHNwYWNlKiogKGV4cG9zdXJlKSBhbmQgKip3ZWVrbHkgcGh5c2ljYWwgYWN0aXZpdHkgdGltZSoqIChvdXRjb21lKSwgYWRqdXN0aW5nIGZvciBwb3RlbnRpYWwgY29uZm91bmRlcnMgKHNleCwgYWdlLCBzZXMpLiAKCmBgYHtyfQpzdW1tYXJ5KG1vZGVsX25ldHdvcmspCmBgYAo8ZGl2IHN0eWxlPSJjb2xvcjogZ3JlZW47IGZvbnQtZmFtaWx5OiAnR2VvcmdpYScsIHNlcmlmOyBmb250LXNpemU6IDE2cHg7IGZvbnQtd2VpZ2h0OiBub3JtYWw7Ij4KICA8c3Ryb25nPkludGVycHJldGF0aW9uPC9zdHJvbmc+PGJyPiBBIDEwMC1tZXRlciBpbmNyZWFzZSBpbiBuZXR3b3JrIGRpc3RhbmNlIHRvIHRoZSBuZWFyZXN0IGdyZWVuIHNwYWNlIGlzIGFzc29jaWF0ZWQgd2l0aCBhIDIuMTQtbWludXRlIGRlY3JlYXNlIGluIHdlZWtseSBwaHlzaWNhbCBhY3Rpdml0eSwgYWRqdXN0aW5nIGZvciBzZXgsIGFnZSwgYW5kIHNvY2lvZWNvbm9taWMgc3RhdHVzLiBUaGUgbW9kZWwgZXhwbGFpbnMgNC4wJSBvZiB0aGUgdmFyaWFuY2UgaW4gd2Vla2x5IHBoeXNpY2FsIGFjdGl2aXR5LiBUaGUgcmVzaWR1YWwgc3RhbmRhcmQgZXJyb3IgaW5kaWNhdGVzIGEgc3Vic3RhbnRpYWwgdW5leHBsYWluZWQgdmFyaWFiaWxpdHkgb2YgYXJvdW5kIDMwIG1pbnV0ZXMuIEFsdGhvdWdoIHRoZSBhc3NvY2lhdGlvbiBpcyBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50IChwIDwgMC4wMDEpLCB0aGUgb3ZlcmFsbCBlZmZlY3Qgc2l6ZSBpcyBzbWFsbCwgYW5kIHRoZSBleHBsYW5hdG9yeSBwb3dlciBpcyBsaW1pdGVkLgo8L2Rpdj4KCgpgYGB7cn0KcDEgPC0gZ2dwbG90KEluc3RvcmF0aW9uLCBhZXMoeCA9IHN0cmFpZ2h0X2Rpc3RhbmNlLCB5ID0gd2Vla2x5X3BhKSkgKwogIGdlb21fcG9pbnQoYWxwaGEgPSAwLjMsIGNvbG9yID0gIiNmZjcwYTYiKSArCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgY29sb3IgPSAiI2ZmMDA1NCIsIGZpbGwgPSAiI0Y3OTZCQiIpICsKICBsYWJzKAogICAgdGl0bGUgPSAiU3RyYWlnaHQtbGluZSB2cy4gUGh5c2ljYWwgQWN0aXZpdHkiLAogICAgeCA9ICJTdHJhaWdodC1saW5lIEdyZWVuIFNwYWNlIChtZXRlcnMpIiwKICAgIHkgPSAiUGh5c2ljYWwgQWN0aXZpdHkgKG1pbnV0ZXMvd2VlaykiCiAgKSArCiAgdGhlbWVfbWluaW1hbChiYXNlX3NpemUgPSAxMCkKYGBgCkNyZWF0ZSBhIHNjYXR0ZXJwbG90IHNob3dpbmcgdGhlIGFzc29jaWF0aW9uIGJldHdlZW4gc3RyYWlnaHQtbGluZSBkaXN0YW5jZSB0byB0aGUgY2xvc2VzdCBncmVlbiBzcGFjZSBhbmQgd2Vla2x5IHBoeXNpY2FsIGFjdGl2aXR5LgoKYGBge3J9CnAyIDwtIGdncGxvdChJbnN0b3JhdGlvbiwgYWVzKHggPSBuZXR3b3JrX2Rpc3RhbmNlLCB5ID0gd2Vla2x5X3BhKSkgKwogIGdlb21fcG9pbnQoYWxwaGEgPSAwLjMsIGNvbG9yID0gIiNFNEIwRUUiKSArCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgY29sb3IgPSAiI0JFMzlEOCIsIGZpbGwgPSAiI0QzOThERiIpICsKICBsYWJzKAogICAgdGl0bGUgPSAiTmV0d29yayB2cy4gUGh5c2ljYWwgQWN0aXZpdHkiLAogICAgeCA9ICJOZXR3b3JrIEdyZWVuIFNwYWNlIChtZXRlcnMpIiwKICAgIHkgPSAiUGh5c2ljYWwgQWN0aXZpdHkgKG1pbnV0ZXMvd2VlaykiCiAgKSArCiAgdGhlbWVfbWluaW1hbChiYXNlX3NpemUgPSAxMCkKYGBgCkNyZWF0ZSBhIHNjYXR0ZXJwbG90IHNob3dpbmcgdGhlIGFzc29jaWF0aW9uIGJldHdlZW4gbmV0d29yayBkaXN0YW5jZSB0byB0aGUgY2xvc2VzdCBncmVlbiBzcGFjZSBhbmQgd2Vla2x5IHBoeXNpY2FsIGFjdGl2aXR5LgoKYGBge3J9CmNvbWJpbmVkX3Bsb3QgPC0gcDEgKyBwMgpjb21iaW5lZF9wbG90CmBgYApDb21iaW5lIHBsb3RzIGZvciBjb21wYXJpc29uIHVzaW5nIHBhdGNod29yay4KCjxkaXYgc3R5bGU9ImNvbG9yOiBncmVlbjsgZm9udC1mYW1pbHk6ICdHZW9yZ2lhJywgc2VyaWY7IGZvbnQtc2l6ZTogMTZweDsgZm9udC13ZWlnaHQ6IG5vcm1hbDsiPgogIDxzdHJvbmc+SW50ZXJwcmV0YXRpb248L3N0cm9uZz48YnI+IFdoaWxlIGJvdGggInN0cmFpZ2h0LWxpbmUgZGlzdGFuY2UiIGFuZCAibmV0d29yayBkaXN0YW5jZSIgdG8gdGhlIG5lYXJlc3QgZ3JlZW4gc3BhY2UgYXJlIHNpZ25pZmljYW50bHkgYXNzb2NpYXRlZCB3aXRoIGxvd2VyIHdlZWtseSBwaHlzaWNhbCBhY3Rpdml0eSwgIm5ldHdvcmsgZGlzdGFuY2UiIHNob3dzIGEgc2xpZ2h0bHkgc3Ryb25nZXIgc3RhdGlzdGljYWwgYXNzb2NpYXRpb24gKHQgPSDigJMxNC4xMyB2cy4g4oCTMTMuNTEpIGFuZCBiZXR0ZXIgbW9kZWwgZml0IChSwrIgPSA0LjAlIHZzLiAzLjYlKS4gVGhlc2UgcmVzdWx0cyBzdWdnZXN0IHRoYXQgbmV0d29yayBkaXN0YW5jZSBvZmZlcnMgYSBtb3JlIHJlYWxpc3RpYyBlc3RpbWF0aW9uIG9mIGdyZWVuIHNwYWNlIGFjY2Vzc2liaWxpdHksIGFzIGl0IGlzIGNvbnN0cnVjdGVkIGJhc2VkIG9uIGFjdHVhbCByb3V0ZXMuCjwvZGl2PgoKWyoqRVhFUkNJU0UgNDoqKiBCaW9kaXZlcnNpdHkgcGF0aHdheV17c3R5bGU9ImZvbnQtc2l6ZToyNHB4OyB0ZXh0LWRlY29yYXRpb246dW5kZXJsaW5lO2NvbG9yOmdyZWVuOyJ9CgpUaGlzIGV4ZXJjaXNlIGZvY3VzZXMgb24gdGhlIGJpb2RpdmVyc2l0eSBwYXRod2F5LiBCaW9kaXZlcnNpdHkgaXMgYSBmdW5kYW1lbnRhbCBkZXRlcm1pbmFudCBvZiBoZWFsdGgsIGluZmx1ZW5jaW5nIGJvdGggcGh5c2ljYWwgYW5kIHBzeWNob2xvZ2ljYWwgd2VsbC1iZWluZy4gV2hpbGUgYmlvZGl2ZXJzaXR5IGdlbmVyYWxseSBiZW5lZml0cyBodW1hbiBoZWFsdGgsIGl0IGFsc28gcHJlc2VudHMgYXNzb2NpYXRlZCByaXNrcywgaW5jbHVkaW5nIGV4cG9zdXJlIHRvIGFpcmJvcm5lIGFsbGVyZ2VucyBhbmQgdm9sYXRpbGUgb3JnYW5pYyBjb21wb3VuZHMgdGhhdCBtYXkgdHJpZ2dlciBhbGxlcmdpYyByZWFjdGlvbnMgKE1hcnNlbGxlIGV0IGFsLiwgMjAyMSkuCgoqKkRFU0NSSVBUSU9OKioKCllvdSB3aWxsIGFuYWx5emUgZ2VuZXJhdGVkIGRhdGEgZnJvbSA0LDczMCBwYXJ0aWNpcGFudHMgdG8gZXhhbWluZSBob3cgdmVnZXRhdGlvbiBkaXZlcnNpdHkgaXMgYXNzb2NpYXRlZCB3aXRoIGFsbGVyZ2ljIHJoaW5pdGlzIHN5bXB0b21zIChlLmcuLCBzbmVlemluZywgbmFzYWwgY29uZ2VzdGlvbiwgaXRjaHkgZXllcyksIG1lYXN1cmVkIGFzIHRoZSB0b3RhbCBudW1iZXIgb2YgYW50aWhpc3RhbWluZSBwaWxscyB0YWtlbiBwZXIgeWVhci4gCgpWZWdldGF0aW9uIGRpdmVyc2l0eSBpcyBtb2RlbGVkIGFzIGEgY29udGludW91cyBpbmRleCBiYXNlZCBvbiB0aGUgU2hhbm5vbiBkaXZlcnNpdHkgaW5kZXgsIHdoaWNoIGFjY291bnRzIGZvciBib3RoIGFidW5kYW5jZSBhbmQgZXZlbm5lc3Mgb2YgdGhlIHNwZWNpZXMgcHJlc2VudC4gVGhlIGluZGV4IHJhbmdlcyBmcm9tIDAgKG5vIGRpdmVyc2l0eSkgdG8gYXBwcm94aW1hdGVseSAyLjUgKGhpZ2ggZGl2ZXJzaXR5KSwgd2l0aCBoaWdoZXIgdmFsdWVzIGluZGljYXRpbmcgZ3JlYXRlciBlY29sb2dpY2FsIGRpdmVyc2l0eSBpbiB0aGUgc3Vycm91bmRpbmcgcGxhbnQgZW52aXJvbm1lbnQuCgpgYGB7cn0KbGlicmFyeShyZWFkcikKQmlvZGl2ZXJzaXR5IDwtIHJlYWRfY3N2KCJCaW9kaXZlcnNpdHkuY3N2IikKYGBgCkxvYWQgdGhlIHN5bnRoZXRpYyBkYXRhc2V0IHRpdGxlZCAiQmlvZGl2ZXJzaXR5LmNzdiIuCgpgYGB7cn0Kc3RyKEJpb2RpdmVyc2l0eSkKYGBgCkV4YW1pbmUgdGhlIHN0cnVjdHVyZSBvZiB0aGUgZGF0YXNldC4gVGhlICJCaW9kaXZlcnNpdHkiIGRhdGFzZXQgc2ltdWxhdGVzIGRhdGEgZm9yIDQsNzMwIGFkdWx0IHBhcnRpY2lwYW50cyB3aXRoIHRoZSBmb2xsb3dpbmcgdmFyaWFibGVzOgoKLSAgICoqaWQqKjogSW5kZW50aWZpY2F0aW9uIG51bWJlcgotICAgKip2ZWdfZGl2ZXJzaXR5Kio6IFZlZ2V0YXRpb24gZGl2ZXJzaXR5IGJhc2VkIG9uIHRoZSBTaGFubm9uIGRpdmVyc2l0eSBpbmRleCwgZXN0aW1hdGVkIHdpdGhpbiBhIDMwMC1tZXRlciBidWZmZXIgYXJvdW5kIGVhY2ggcGFydGljaXBhbnTigJlzIHJlc2lkZW5jZS4KLSAgICoqdXJiYW5pY2l0eSoqOiBVcmJhbml6YXRpb24gbGV2ZWwgKFJ1cmFsLCBTdWJ1cmJhbiBvciBVcmJhbikgb2YgdGhlIG5laWdoYm9yaG9vZCBhcmVhLgotICAgKiphbGxlcmd5X21lZCoqOiBUaGUgdG90YWwgbnVtYmVyIG9mIGFudGloaXN0YW1pbmUgcGlsbHMgY29uc3VtZWQgb3ZlciB0aGUgdGhlIHBhc3QgeWVhciwgYXMgYSBwcm94eSBvZiBhbGxlcmdpYyByaGluaXRpcyBzeW1wdG9tIGJ1cmRlbi4KLSAgICoqc2V4Kio6IFNleCAoRmVtYWxlIG9yIE1hbGUpCi0gICAqKmFnZSoqOiBBZ2UgKHllYXJzKQotICAgKipzZXMqKjogU29jaW9lY29ub21pYyBzdGF0dXMgKEkgKGhpZ2hlc3QpIHRvIFYgKGxvd2VzdCkpCgoKYGBge3J9CkJpb2RpdmVyc2l0eSR1cmJhbmljaXR5IDwtIGZhY3RvcihCaW9kaXZlcnNpdHkkdXJiYW5pY2l0eSwgbGFiZWxzID0gYygiUnVyYWwiLCAiU3VidXJiYW4iLCAiVXJiYW4iKSkKQmlvZGl2ZXJzaXR5JHNleCA8LSBmYWN0b3IoQmlvZGl2ZXJzaXR5JHNleCwgbGFiZWxzID0gYygiRmVtYWxlIiwgIk1hbGUiKSkKQmlvZGl2ZXJzaXR5JHNlcyA8LSBmYWN0b3IoQmlvZGl2ZXJzaXR5JHNlcywgbGFiZWxzID0gYygiSSIsICJJSSIsICJJSUkiLCAiSVYiLCAiViIpKQpgYGAKUmVjb2RlIGNhdGVnb3JpY2FsIHZhcmlhYmxlcyBpbiB0aGUgIkJpb2RpdmVyc2l0eSIgZGF0YXNldCBhcyBmYWN0b3IuCgpgYGB7cn0KbGlicmFyeShza2ltcikKc2tpbShCaW9kaXZlcnNpdHlbLCBjKCJ2ZWdfZGl2ZXJzaXR5IiwgImFsbGVyZ3lfbWVkIildKQpgYGAKQ2hlY2sgdGhlIGRpc3RyaWJ1dGlvbiBvZiB0aGUgZXhwb3N1cmUgYW5kIG91dGNvbWUgdmFyaWFibGVzLiAKCmBgYHtyfQptb2RlbF9iaW9kaXZlcnNpdHkgPC0gbG0oYWxsZXJneV9tZWQgfiB2ZWdfZGl2ZXJzaXR5ICsgc2V4ICsgYWdlICsgc2VzLCBkYXRhID0gQmlvZGl2ZXJzaXR5KQpgYGAKRml0IGEgbGluZWFyIHJlZ3Jlc3Npb24gbW9kZWwgdG8gZXhhbWluZSB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gKip2ZWdldGF0aW9uIGRpdmVyc2l0eSoqIChleHBvc3VyZSkgYW5kICoqYW50aWhpc3RhbWluZSBwaWxscyBwZXIgeWVhcioqIChvdXRjb21lKSwgYWRqdXN0aW5nIGZvciBwb3RlbnRpYWwgY29uZm91bmRlcnMgKHNleCwgYWdlLCBzZXMpLiAKCmBgYHtyfQpzdW1tYXJ5KG1vZGVsX2Jpb2RpdmVyc2l0eSkKYGBgCjxkaXYgc3R5bGU9ImNvbG9yOiBncmVlbjsgZm9udC1mYW1pbHk6ICdHZW9yZ2lhJywgc2VyaWY7IGZvbnQtc2l6ZTogMTZweDsgZm9udC13ZWlnaHQ6IG5vcm1hbDsiPgogIDxzdHJvbmc+SW50ZXJwcmV0YXRpb248L3N0cm9uZz48YnI+IEEgdW5pdCBpbmNyZWFzZSBpbiB2ZWdldGF0aW9uIGRpdmVyc2l0eSBpcyBhc3NvY2lhdGVkIHdpdGggYW4gZXN0aW1hdGVkIGluY3JlYXNlIG9mIDQuNTIgYW50aWhpc3RhbWluZSBwaWxscyBwZXIgeWVhciwgYWRqdXN0aW5nIGZvciBzZXgsIGFnZSwgYW5kIHNvY2lvZWNvbm9taWMgc3RhdHVzIChwIDwgMC4wMDEpLiBUaGUgbW9kZWwgZXhwbGFpbnMgMTkuMyUgb2YgdGhlIHZhcmlhbmNlIGluIGFudGloaXN0YW1pbmUgdXNlLCB3aXRoIGEgcmVzaWR1YWwgc3RhbmRhcmQgZXJyb3Igb2YgMy40MiBwaWxscywgd2hpY2ggaW5kaWNhdGVzIGEgbW9kZXJhdGUgdW5leHBsYWluZWQgdmFyaWFiaWxpdHkuIAoKPC9kaXY+CgpgYGB7cn0KbGlicmFyeShkcGx5cikKbGlicmFyeShicm9vbSkKCm1vZGVsX2NvZWZmaWNpZW50c191cmJhbmljaXR5IDwtIEJpb2RpdmVyc2l0eSAlPiUKICBncm91cF9ieSh1cmJhbmljaXR5KSAlPiUKICBkbyh0aWR5KGxtKGFsbGVyZ3lfbWVkIH4gdmVnX2RpdmVyc2l0eSArIHNleCArIGFnZSArIHNlcywgZGF0YSA9IC4pKSkgJT4lCiAgZmlsdGVyKHRlcm0gPT0gInZlZ19kaXZlcnNpdHkiKSAgCmBgYApGaXQgdGhlIHByZXZpb3VzIGxpbmVhciByZWdyZXNzaW9uIG1vZGVsLCBidXQgdGhpcyB0aW1lIHN0cmF0aWZpZWQgYnkgKip1cmJhbml6YXRpb24gbGV2ZWwqKi4gVGhpcyBhcHByb2FjaCBhbGxvd3MgdG8gZXhhbWluZSB3aGV0aGVyIHRoZSBzdHJlbmd0aCBvciBkaXJlY3Rpb24gb2YgdGhlIGFzc29jaWF0aW9uIGJldHdlZW4gdmVnZXRhdGlvbiBkaXZlcnNpdHkgYW5kIGFsbGVyZ2ljIHJoaW5pdGlzIHN5bXB0b21zIHZhcmllcyBhY3Jvc3MgcnVyYWwsIHN1YnVyYmFuLCBhbmQgdXJiYW4gcmVzaWRlbnRpYWwgY29udGV4dHMuCgoKYGBge3J9CnByaW50KG1vZGVsX2NvZWZmaWNpZW50c191cmJhbmljaXR5KQpgYGAKPGRpdiBzdHlsZT0iY29sb3I6IGdyZWVuOyBmb250LWZhbWlseTogJ0dlb3JnaWEnLCBzZXJpZjsgZm9udC1zaXplOiAxNnB4OyBmb250LXdlaWdodDogbm9ybWFsOyI+CiAgPHN0cm9uZz5JbnRlcnByZXRhdGlvbjwvc3Ryb25nPjxicj4gV2hlbiBzdHJhdGlmaWVkIGJ5IHVyYmFuaXphdGlvbiBsZXZlbCwgdGhlIGFzc29jaWF0aW9uIGJldHdlZW4gdmVnZXRhdGlvbiBkaXZlcnNpdHkgYW5kIGFudGloaXN0YW1pbmUgdXNlIGRpZmZlcnMgaW4gbWFnbml0dWRlLiBJbiB1cmJhbiBhcmVhcywgYSB1bml0IGluY3JlYXNlIGluIHZlZ2V0YXRpb24gZGl2ZXJzaXR5IGlzIGFzc29jaWF0ZWQgd2l0aCBhbiBlc3RpbWF0ZWQgNC40NyBwaWxsIGluY3JlYXNlIHBlciB5ZWFyIChwIDwgMC4wMDEpLCBhZnRlciBhZGp1c3RpbmcgZm9yIHNleCwgYWdlLCBhbmQgc29jaW9lY29ub21pYyBzdGF0dXMuIEluIHN1YnVyYmFuIGFyZWFzLCB0aGUgaW5jcmVhc2UgY29ycmVzcG9uZHMgdG8gMS40MSBwaWxscyBwZXIgeWVhciAocCA8IDAuMDAxKSwgd2hpbGUgaW4gcnVyYWwgYXJlYXMsIHRoZSBhc3NvY2lhdGlvbiBpcyBzbWFsbGVyIGF0IDAuNTYgcGlsbHMgcGVyIHllYXIgKHAgPCAwLjAwMSkuIFRoZXNlIHJlc3VsdHMgc3VnZ2VzdCB0aGF0IHRoZSBoZWFsdGggaW1wYWN0IG9mIHZlZ2V0YXRpb24gZGl2ZXJzaXR5IG1heSBiZSBtb2RpZmllZCBieSB1cmJhbml6YXRpb24gbGV2ZWwuCjwvZGl2PgoKCmBgYHtyfQpnZ3Bsb3QoQmlvZGl2ZXJzaXR5LCBhZXMoeCA9IHZlZ19kaXZlcnNpdHksIHkgPSBhbGxlcmd5X21lZCwgY29sb3IgPSB1cmJhbmljaXR5KSkgKwogIGdlb21fcG9pbnQoYWxwaGEgPSAwLjQpICsKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IEZBTFNFLCBzaXplID0gMS4yKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKAogICAgdmFsdWVzID0gYygiUnVyYWwiID0gIiMwQkRBNTEiLCAiU3VidXJiYW4iID0gIiMxRTkwRkYiLCAiVXJiYW4iID0gIiNGRjM4MDAiKSAgIyB5b3UgY2FuIGNoYW5nZSB0aGVzZQogICkgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJWZWdldGF0aW9uIERpdmVyc2l0eSB2cy4gQWxsZXJneSBNZWRpY2F0aW9uIiwKICAgIHggPSAiVmVnZXRhdGlvbiBEaXZlcnNpdHkiLAogICAgeSA9ICJBbGxlcmd5IE1lZGljYXRpb24gKHBpbGxzL3llYXIpIiwKICAgIGNvbG9yID0gIlVyYmFuaXphdGlvbiIKICApICsKICB0aGVtZV9taW5pbWFsKCkKCmBgYAo8ZGl2IHN0eWxlPSJjb2xvcjogZ3JlZW47IGZvbnQtZmFtaWx5OiAnR2VvcmdpYScsIHNlcmlmOyBmb250LXNpemU6IDE2cHg7IGZvbnQtd2VpZ2h0OiBub3JtYWw7Ij4KICA8c3Ryb25nPkludGVycHJldGF0aW9uPC9zdHJvbmc+PGJyPgpUaGUgcmVsYXRpb25zaGlwIGJldHdlZW4gdXJiYW5pemF0aW9uIGFuZCBhbGxlcmdpYyBzeW1wdG9tcyAoZS5nLixhc3RobWEsIGFsbGVyZ2ljIHJoaW5pdGlzLCBlY3plbWEsIGZvb2QgYWxsZXJnaWVzKSBoYXMgYmVlbiB3aWRlbHkgc3R1ZGllZCwgYW5kIGVwaWRlbWlvbG9naWNhbCBldmlkZW5jZSBjb25zaXN0ZW50bHkgc2hvd3MgaGlnaGVyIHByZXZhbGVuY2UgYW5kIHNldmVyaXR5IG9mIGFsbGVyZ2ljIGRpc2Vhc2VzIGFtb25nIGluZGl2aWR1YWxzIHJlc2lkaW5nIGluIHVyYmFuIGFyZWFzIHdoZW4gY29tcGFyZWQgdG8gdGhvc2UgdGhhdCByZXNpZGUgaW4gcnVyYWwgc2V0dGluZ3MuVGhpcyBhc3NvY2lhdGlvbiBtYXkgYmUgcGFydGx5IGF0dHJpYnV0ZWQgdG8gcmVkdWNlZCBtaWNyb2JpYWwgZXhwb3N1cmUgaW4gdXJiYW4gZW52aXJvbm1lbnRzLiBVcmJhbml6YXRpb24gaGFzIGJlZW4gYXNzb2NpYXRlZCB0byBsb3dlciBtaWNyb2JpYWwgZGl2ZXJzaXR5LCB3aGljaCBpcyBjb25zaWRlcmVkIGFuIGltcG9ydGFudCBmYWN0b3IgaW4gdGhlIGRldmVsb3BtZW50IG9mIGFsbGVyZ2ljIHNlbnNpdGl6YXRpb24uIEFjY29yZGluZyB0byB0aGUgaHlnaWVuZSBoeXBvdGhlc2lzLCByZWR1Y2VkIGV4cG9zdXJlIHRvIG1pY3JvYmVzIGluIGVhcmx5IGxpZmUgbGltaXRzIGltbXVuZSBzeXN0ZW0gc3RpbXVsYXRpb24sIHBvdGVudGlhbGx5IGluY3JlYXNpbmcgdGhlIHJpc2sgb2YgYWxsZXJnaWMgZGlzZWFzZXMuCgo8L2Rpdj4KCjxkaXYgc3R5bGU9InRleHQtYWxpZ246IGNlbnRlcjsiPgogIDxoMSBzdHlsZT0iZm9udC1zaXplOiAzMHB4OyBmb250LXdlaWdodDogYm9sZDsgbWFyZ2luLWJvdHRvbTogMDsiPgogICAgRW5kIG9mIHRoZSBhbmFseXNpcyDigJQgVGhhbmsgeW91IGZvciBqb2luaW5nIHRoZSB3b3Jrc2hvcCEKICA8L2gxPgogIAogIAogIAogIAo8L2Rpdj4KCgoK